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



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

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);
    }

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

我将其重构为:

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方法中的每个表添加了一行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个简单的查找表。当我看到上面的100行代码时,它看起来不太对劲。

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

我的问题:

  1. 提供服务真的是最好的做法吗。为Startup.csConfigureServices方法中的每个查找表添加Scoped?

  2. 这是一个通用的存储库,难道没有办法将这100行复制粘贴到一行中吗?

  3. 如果没有,那么使用我的代码实现这一点的最佳实践方法是什么?

只需使用非通用注册重载(需要传递2个Type对象的重载),然后提供接口和实现的开放通用类型:

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

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

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

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

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

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

最新更新