ASP.NET Core 中的通用存储库没有在 Startup.cs 中每个 table 单独的 AddScoped 行?

Generic repository in ASP.NET Core without having a separate AddScoped line per table in Startup.cs?

我的项目中有一个通用存储库。 考虑以下控制器片段

public class Lookup1Controller : Controller
{
    readonly MyDbContext _db;

    public Lookup1Controller(MyDbContext dataContext)
    {
        _db = dataContext;
    }

    public async Task<IActionResult> Index()
    {

        IGenericRepository<Lookup1> _repository = new GenericRepository<Lookup1>(_db);
        var lookup1s = await _repository.SelectAll();

        return  View(lookup1s);
    }

我认为没有必要在我的通用存储库和我的每个控制器中都引用我的数据库。

我将其重构为:

public class Lookup1Controller : Controller
{
    private IGenericRepository<Lookup1> _repository;

    public Lookup1Controller(IGenericRepository<Lookup1> repository)
    {
        _repository = repository;
    }

    public async Task<IActionResult> Index()
    {
        var lookup1s = await _repository.SelectAll();

        return  View(lookup1s);
    }

}

这是我读到的 ASP.NET 5 个最佳实践。 但如果我在浏览器中访问该控制器路由,我将收到以下错误:

InvalidOperationException: Unable to resolve service for type 'MyProject.Data.IGenericRepository`1[MyProject.Models.Lookup1]' while attempting to activate 'MyProject.Controllers.Lookup1.

因为我还没有注入GenericRepository来使用接口

我在 Startup.cs 中为 ConfigureServices 方法中的每个 table 添加了一个 AddScoped

services.AddScoped<IGenericRepository<Lookup1>,GenericRepository<Lookup1>> ();
services.AddScoped<IGenericRepository<Lookup2>,GenericRepository<Lookup2>> ();
services.AddScoped<IGenericRepository<Lookup3>,GenericRepository<Lookup3>> ();
services.AddScoped<IGenericRepository<Lookup4>,GenericRepository<Lookup4>> ();
etc

这样我的代码 运行 就不会抛出异常。

但是我的数据库有大约 100 个简单查找 table。当我查看上面的 100 行代码时,它看起来不对。

感觉就像复制粘贴代码。每次我通过添加一个新的模型和控制器来添加一个新的 table 时,我的代码都会编译而不会给我一个错误。但是,如果我 运行 程序并转到那个视图,如果我忘记将 AddScoped 行添加到我的 Startup.cs,我可能会得到控制器 运行 错误。可维护性不是很好。

我的问题:

  1. Startup.csConfigureServices 方法中为每个查找 table 设置一个 services.AddScoped 真的是最佳实践吗?

  2. 它是一个通用存储库,所以没有办法将这 100 行复制和粘贴写在一行中吗?

  3. 如果不是,那么使用我的代码执行此操作的最佳实践方法是什么?

只需使用非通用注册重载(需要传递 2 个 Type 对象的重载。)然后提供接口和实现的 open generic types

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

在您的控制器中,为特定类型(封闭的通用类型)的存储库添加依赖项:

public HomeController(IGenericRepository<Lookup1> repository)
{
    ...
}

如果您想在汇编中注册所有 IGenericRepository<> 实现:

services.AddAllGenericTypes(typeof(IGenericRepository<>), new[] {typeof(MyDbContext).GetTypeInfo().Assembly});

扩展名来自: https://gist.github.com/GetoXs/5caf0d8cfe6faa8a855c3ccef7c5a541