C# 如何使用使用带有依赖项注入的泛型的存储库接口?
我正在尝试使用以下通用存储库接口进行DI和构造函数注入:C# 如何使用使用带有依赖项注入的泛型的存储库接口?,c#,dependency-injection,unity-container,ioc-container,C#,Dependency Injection,Unity Container,Ioc Container,我正在尝试使用以下通用存储库接口进行DI和构造函数注入: public interface IRepository<TEntity> : IDisposable where TEntity : class 公共接口IRepository:IDisposable其中tenty:class 问题是为了定义接口的实例,我必须提供如下类类型: private IRepository<Person> _personRepository; public MyClass(IRep
public interface IRepository<TEntity> : IDisposable where TEntity : class
公共接口IRepository:IDisposable其中tenty:class
问题是为了定义接口的实例,我必须提供如下类类型:
private IRepository<Person> _personRepository;
public MyClass(IRepository<Person> personRepository,
IRepository<Orders> ordersRepository,
IRepository<Items> itemsRepository,
IRepository<Locations> locationsRepository)
{
_personRepository = personRepository;
_OrdersRepository = ordersRepository;
_itemsRepository = itemsRepository;
_locationsRepository = locationsRepository;
}
private IRepository\u personRepository;
问题是,如果我使用DI(并且我使用Unity for IoC framework),那么我必须在构造函数中定义多个实例,以获得我需要使用的所有存储库接口,如下所示:
private IRepository<Person> _personRepository;
public MyClass(IRepository<Person> personRepository,
IRepository<Orders> ordersRepository,
IRepository<Items> itemsRepository,
IRepository<Locations> locationsRepository)
{
_personRepository = personRepository;
_OrdersRepository = ordersRepository;
_itemsRepository = itemsRepository;
_locationsRepository = locationsRepository;
}
公共MyClass(IRepository personRepository,
i假定顺序假定,
i假定项目假定,
i存储位置(存储位置)
{
_personRepository=personRepository;
_OrdersRepository=OrdersRepository;
_itemsRepository=itemsRepository;
_locationsRepository=locationsRepository;
}
问题:
一个原因是,您可以单元测试
MyClass
,而无需使用实际的数据库存储库。你可以“假”出存储库来返回硬编码的值来进行测试。 你可以考虑使用捆绑在一起的几个其他服务,但是你也应该仔细看看你的<代码> MyClass < /代码>是什么;拥有大量的依赖关系可以说明这一点。除了缺少一点之外,这似乎还可以;您需要UnitOfWork模式来启用事务。
如果不应用UnitOfWork模式,所有存储库都会尝试在不同的上下文中提交db操作。正如D Stanley所指出的,依赖项必须是一个具体的接口。否则,您将在哪里申报T?依赖类可以是泛型的,但在某个时候仍然必须说“T是个人” 这就是说,Unity可以很好地处理注册泛型类型 假设您使用一个通用类
Repository
实现IRepository
,该类封装了DbSet
(或其他)
随后将进行以下注册和解决(包括注入任何施工人员):
解析IRespository
现在将获得您的具体实现
作为记录,我认为这只能在代码中完成,而不能在配置文件中完成。有人可以随意纠正这个假设。我需要使用配置文件来完成这项工作。这其实很简单,但我花了一段时间才弄明白 在本例中,我们有一个接口
IRepository
,它有两个实现:
OneRepository
TwoRepository
Worker
的类,它依赖于IRepository
和IRepository
。我们要求unity为我们创建一个Worker
实例,并从配置文件中找出依赖项
接口和实现
在本例中,所有这些都位于命名空间控制台应用程序1
中
我希望我能做的是将
IRepository repository
作为方法参数,但我知道这不起作用。你能解释一下为什么不会吗?把所有这些都传进来感觉不太好,但也许这是正确的,而且我考虑过了。因为每个存储库都是不同的类型,MyClass(显然)需要4个不同的存储库。您必须单独提供具体的类。以您的方式注入多个依赖项并不是错误的(或不常见的)。但是在什么情况下我需要额外的方法呢?在这种特殊情况下,聚合服务是call a。您可以在Unity配置文件中注册泛型类。我已经做到了<代码>就是一个例子。爱我团结一点。他的问题中没有任何东西指向他需要UoW。正如其他人指出的,也许他的类做得太多了,但他从来没有说过要同时提交对所有存储库的修改。另外,从技术上讲,不同的存储库不一定使用不同的上下文。
public class Worker
{
private readonly IRepository<One> one;
private readonly IRepository<Two> two;
public Worker(IRepository<One> one, IRepository<Two> two)
{
this.one = one;
this.two = two;
}
public string DoOne()
{
return this.one.Add(new One());
}
public string DoTwo()
{
return this.two.Add(new Two());
}
}
public interface IRepository<T>
{
string Add(T t);
}
public class OneRepository : IRepository<One>
{
public string Add(One t)
{
return "One";
}
}
public class TwoRepository : IRepository<Two>
{
public string Add(Two t)
{
return "Two";
}
}
public class One { }
public class Two { }
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="ConsoleApplication1" />
<container>
<register type="ConsoleApplication1.IRepository[[ConsoleApplication1.One]]" mapTo="ConsoleApplication1.OneRepository" />
<register type="ConsoleApplication1.IRepository[[ConsoleApplication1.Two]]" mapTo="ConsoleApplication1.TwoRepository" />
</container>
</unity>
</configuration>
public class Program
{
static void Main()
{
UnityContainer container = new UnityContainer();
var res = container.LoadConfiguration();
Worker worker = res.Resolve<Worker>();
Console.WriteLine(worker.DoOne());
Console.WriteLine(worker.DoTwo());
Console.Read();
}
}
One
Two