首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有泛型和DI的存储库模式

带有泛型和DI的存储库模式
EN

Stack Overflow用户
提问于 2012-10-16 00:38:00
回答 2查看 2.4K关注 0票数 1

我有一个基础存储库合同,其他合同可以扩展,如下所示

代码语言:javascript
复制
public interface IBaseRepository<T> where T : class 
{
  IList<T> GetContents();
}

然后,还有其他一些合同对其进行了扩展,如下所示

代码语言:javascript
复制
public interface IRepository1 : IBaseRepository<MyClass1>
{
}

public interface IRepository2 : IBaseRepository<MyClass2>
{
}

我按如下方式实现IRepository1

代码语言:javascript
复制
public class Repository1 : IRepository1
{
 public IList<MyClass1> GetContents()
 {
  //some code goes here
 }
} 

IRepository2也是如此

代码语言:javascript
复制
public class Repository2 : IRepository2
{
 public IList<MyClass2> GetContents()
 {
  //some code goes here
 }
} 

现在我有了一个实现IService的服务Service1,如下所示

代码语言:javascript
复制
public class Service1 : IService
{


}

我想在我的服务构造函数中使用我的基本存储库(IBaseRepository),获得这个基本存储库的一个实例,并像这样使用它

代码语言:javascript
复制
 public class Service1 : IService
 {
   private IBaseRepository<T> _baseRepository;
   public Service1(IBaseRepository<T> baseRepository)
   {
     _baseRepository = baseRepository;
   }

   public MyMethod1()
   {
      var contentsOfType1 = _baseRepository<MyClass1>.GetContents();
   }

   public MyMethod1()
   {
      var contentsOfType2 = _baseRepository<MyClass2>.GetContents();
   }
  }

而这正是我无法做到的。

因此,我有一个带有类型T的通用基础存储库契约,还有一些扩展基础契约的其他契约(接口),还指定了T的类型。

所有这些契约(扩展泛型基础契约)都有各自的实现。

我想要做的是在我的服务类中,实例化这个泛型基础契约,并使用它来推断扩展类型(以及实现),并使用基础存储库中的方法。

因此,如果基础合约是IBaseRepository<T>

并且扩展合同是IRepository1 : IBaseRepository<MyClass1>

它由Repository1 : IRepository1实现

我想在我的服务类中使用它,比如

代码语言:javascript
复制
public class service()
{
   *private IBaseRepository<T> _repo;

   public  service(IBaseRepository<T> repo)
   { 
    *_repo = repo;
   } 

   public void MyMethod()
   {

     *var x = _repo<MyClass1>.MethodFromIBaseRepository()
   }

}

所以这是我想要实现的*标记行,但我无法实现。

我在用城堡温莎做DI。

谢谢你们的帮助

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-16 23:16:49

除了通用IRepository<T>之外,您不应该有其他存储库接口。如果您需要这些,那么您就缺少了一个抽象。

例如,人们拥有自定义存储库接口的一个常见原因是,他们有一个自定义查询,而另一些存储库则没有。例如:

代码语言:javascript
复制
public interface IEmployeeRepository : IRepository<Employee>
{
    Employee GetEmployeeOfTheMonth(int month);
}

这里的问题是IEmployeeRepository被滥用来进行“自定义查询”。自定义查询应该有自己的(通用)抽象:

代码语言:javascript
复制
// Defines a query
public interface IQuery<TResult>
{
}

// Defines the handler that will execute queries
public interface IQueryHandler<TQuery, TResult>
    where TQuery : IQuery<TResult>
{
    TResult Handle(TQuery query);
}

有了这个抽象,我们可以向系统添加自定义查询,而不需要创建IRepository<T>派生:

代码语言:javascript
复制
public class GetEmployeeOfTheMonthQuery : IQuery<Employee>
{
    [Range(1, 12)]
    public int Month { get; set; }
}

class GetEmployeeOfTheMonthHandler : IQueryHandler<GetEmployeeOfTheMonthQuery, Employee>
{
    public Employee Handle(GetEmployeeOfTheMonthQuery query)
    {
        // todo: query the database, web service, disk, what ever.
    }
}

需要知道当月雇员的消费者现在可以简单地依赖IQueryHandler<GetEmployeeOfTheMonthQuery, Employee>并执行查询,如下所示:

代码语言:javascript
复制
var query = new GetEmployeeOfTheMonthQuery { Month = 11 };
var employee = this.employeeOfMonthHandler.Handle(query);

这可能看起来像是开销,但这种模型非常灵活、可伸缩,并具有许多有趣的好处。例如,很容易通过用装饰器包装处理程序来添加横切关注点。

这也允许我们的代码库隐藏在一个通用接口后面,这使得我们可以轻松地一次性批量注册它们,并向它们添加装饰器。

有关更深入的信息,请阅读本文:Meanwhile… on the query side of my architecture

票数 8
EN

Stack Overflow用户

发布于 2012-10-16 13:34:33

不可能。控制反转容器通过构造函数提供依赖关系,因此它必须在构造函数中知道您想要获取什么类型。所以你应该这样做:

代码语言:javascript
复制
public class service()
{
   private IBaseRepository<MyClass1> _repo;

   public  service(IBaseRepository<MyClass1> repo)
   { 
       _repo = repo;
   } 

   public void MyMethod()
   {

      var x = _repo.MethodFromIBaseRepository()
   }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12900078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档