如何使用具有依赖注入的泛型的存储库接口?

atc*_*way 13 c# dependency-injection ioc-container unity-container

我试图使用以下通用存储库接口进行DI和构造函数注入:

public interface IRepository<TEntity> : IDisposable where TEntity : class
Run Code Online (Sandbox Code Playgroud)

问题是为了定义接口的实例,我必须提供类似这样的类类型:

private IRepository<Person> _personRepository;
Run Code Online (Sandbox Code Playgroud)

这个问题是如果我使用DI(我使用Unity for IoC框架),那么我必须在构造函数中定义多个实例以获取我需要使用的所有存储库接口,如下所示:

public MyClass(IRepository<Person> personRepository,
               IRepository<Orders> ordersRepository,
               IRepository<Items> itemsRepository,
               IRepository<Locations> locationsRepository)
{
  _personRepository = personRepository;
  _OrdersRepository = ordersRepository; 
  _itemsRepository = itemsRepository;
  _locationsRepository = locationsRepository;
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 这个可以吗?
  2. 如果不是我在这个概念上失去了什么?
  3. 即使这是正确的,Unity将接口注册到具体类型的重点是什么?我已经做到了,因为通用存储库迫使我申报.

请帮助我解决这个问题,感谢您的帮助!

Nic*_*ick 10

正如D Stanley所指出的,依赖必须是具体的接口.否则,你要在哪里宣布T?您的依赖类可能是通用的,但您仍然必须在某个时候说"T是一个人".

也就是说,Unity处理非常好的注册泛型类型.

假设您IRepository<T>使用Repository<T>包装DbSet<T>(或其他)的泛型类来实现.

然后,以下注册和结算将起作用(包括注入任何构造函数):

container.RegisterType(typeof(IRepository<>), typeof(Repository<>));

// no specific registration needed for the specific type resolves
container.Resolve(<IRepository<Person>);
container.Resolve(<IRepository<Order>); 
Run Code Online (Sandbox Code Playgroud)

如果您需要某种类型的特定覆盖(表示Items存储库因任何原因而特殊,因此它具有完全实现的ItemRepository类),只需在通用类之后注册该特定实现:

container.RegisterType<IRepository<Item>, ItemRepository>();
Run Code Online (Sandbox Code Playgroud)

解决方案IRespository<Item>现在将获得您的具体实施.

为了记录,我认为这只能在代码中完成,而不能在配置文件中完成.有人可以随意纠正这个假设.


D S*_*ley 2

这个可以吗?

当然。对于是否像您一样使用构造函数注入或属性注入,存在个人偏好。构造函数注入更干净,因为您不必向构造函数提供大量参数,但它也更安全。

Unity将接口注册到具体类型有什么意义

原因之一是您可以进行单元测试,MyClass而无需使用访问数据库的实际存储库。您可以“伪造”存储库以返回硬编码值以进行测试。