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

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

我将其重构为:

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 来使用接口。

我为 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方法中的每个查找表添加作用域?

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

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

54041 次浏览

Just use the non-generic registration overloads (the ones where you need to pass the 2 Type objects.) Then provide the open generic types of both your interface and the implementation:

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

In your controller, add a dependency for a repository of a specific type (a closed generic type):

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

If you would like to register all IGenericRepository<> implementations in Assembly:

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

With extension from: https://gist.github.com/GetoXs/5caf0d8cfe6faa8a855c3ccef7c5a541