Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用使用带有依赖项注入的泛型的存储库接口?_C#_Dependency Injection_Unity Container_Ioc Container - Fatal编程技术网

C# 如何使用使用带有依赖项注入的泛型的存储库接口?

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

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

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