【问题标题】:Dependency Injection and Generic Collections依赖注入和泛型集合
【发布时间】:2009-11-06 09:17:02
【问题描述】:

我目前正在兜圈子,试图找到正确的模式,以便将依赖注入与多个 IEnumerables 一起使用。

我想从我的数据库中返回三种类型的对象:项目、批次和任务。我想创建一个具有以下形式的存储库:

public interface IRepository<T>
{
    IEnumerable<T> GetAll();
    IEnumerable<T> GetAllActive();
    IEnumerable<T> GetItemsByUserName(string UserName);
    T GetItemById(int ID);
}

所以当我创建一个 ProjectRepository 的具体实现时,它将如下所示:

IEnumerable<Project> GetAll();
IEnumerable<Project> GetAllActive();
IEnumerable<Project> GetItemsByUserName(string UserName);
Project GetItemById(int ID);

对于任务也是如此:

IEnumerable<Task> GetAll();
IEnumerable<Task> GetAllActive();
IEnumerable<Task> GetItemsByUserName(string UserName);
Task GetItemById(int ID);

我的困难在于尝试在我的调用代码中声明一个 IRepository。当我声明引用时,我发现自己需要声明一个类型:

private IRepository<Project> Repository;

...这当然是没有意义的。我在某个地方出错了,但目前无法理解。如何使用依赖注入来声明一个使用所有三种具体类型的接口?

希望我已经正确解释了自己。

【问题讨论】:

    标签: design-patterns generics collections dependency-injection


    【解决方案1】:

    使用泛型:

    public class YourClass<T>
    {
        public YourClass(IRepository<T> repository)
        {
            var all = repository.GetAll();
        }
    }
    

    当然,在某些时候你需要提供T,它可能看起来像这样:

    var projectClass = yourDIContainer.Resolve<YourClass<Project>>;
    

    在向 DI 容器注册类型方面,如果您的 DI 容器支持开放泛型,这可能会很有用。例如,查看 this post,它显示了 Unity 如何支持这一点。

    【讨论】:

      【解决方案2】:

      希望这对您编写代码的方式有所帮助。

      public class Repository : IRepository<Repository>
      {
      
          public Repository()
          {
          }
      
          #region IRepository<Repository> Members
      
          public IEnumerable<Repository> GetAll()
          {
              throw new Exception("The method or operation is not implemented.");
          }
      
          public IEnumerable<Repository> GetAllActive()
          {
              throw new Exception("The method or operation is not implemented.");
          }
      
          public IEnumerable<Repository> GetItemsByUserName(string UserName)
          {
              throw new Exception("The method or operation is not implemented.");
          }
      
          public Repository GetItemById(int ID)
          {
              throw new Exception("The method or operation is not implemented.");
          }
      
          #endregion
      }
      
      
      
      public class RepositoryCreator<T> where T : IRepository<T>
      {
          public IRepository<Repository> getRepository()
          {
              Repository r = new Repository();
              return r;
          }
      
      
          public IRepository<Blah> getBlah()
          {
              Blah r = new Blah();
              return r;
          }
      }
      

      【讨论】:

        【解决方案3】:

        鉴于您已将存储库接口定义为返回特定类型,为什么您认为在客户端代码中提供您期望它返回的类型毫无意义?

        如果你不关心返回类型是没有意义的,但是整个通用接口设计是没有意义的。

        如果您希望存储库对象仅适用于指定类型,那么您将需要三个对象(或可能具有三个接口的对象,具体取决于实现语言)来提供您的项目存储库、批处理存储库和任务存储库。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-09
          • 1970-01-01
          相关资源
          最近更新 更多