泛型和DI存储库模式 [英] Repository pattern with generics and DI

查看:110
本文介绍了泛型和DI存储库模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基础库的合同而其他合同延伸,就像如下

I have a base repository contract which other contracts extend, like follows

public interface IBaseRepository<T> where T : class 
{
  IList<T> GetContents();
}



再有它扩展它喜欢跟随其他合约

and then there are other contracts which extend it like follows

public interface IRepository1 : IBaseRepository<MyClass1>
{
}

public interface IRepository2 : IBaseRepository<MyClass2>
{
}



我实现IRepository1如下:

I implement IRepository1 as follows

public class Repository1 : IRepository1
{
 public IList<MyClass1> GetContents()
 {
  //some code goes here
 }
} 

同样,对于IRepository2

similarly for IRepository2

public class Repository2 : IRepository2
{
 public IList<MyClass2> GetContents()
 {
  //some code goes here
 }
} 

现在我有implments IService喜欢遵循服务服务1

Now i have a service Service1 which implments IService like follows

public class Service1 : IService
{


}

我想用我的基地库(IBaseRepository)在这里我的服务构造,获得此基础库的实例,并使用它像这样

I want to use my base repository (IBaseRepository) here in my service constructor, get an instance of this base repository and use it like so

 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。

So i have a generic base repository contract with type T and have other contracts (interfaces) extending the base contract and also specifying what type T will be.

所有这些合同(其中延长通用基本合同)有thier单独实现。

All these contracts (which extend generic base contract) have thier individual implementations.

我想要做的就是在我的服务类,实例化这个通用的基本合同,并用它来推断延伸类型(因此实现),并从使用的方法。基本信息库

What i want to do is in my service class, instantiate this generic base contract, and use it to infer the extending types (and hence implementations) and use the method from the base repository.

因此,如果基本合同是
IBaseRepository< T>

So if the base contract is IBaseRepository<T>

和延长合同是
IRepository1:IBaseRepository< MyClass1的>

这是由
实施 Repository1:IRepository1

我想在我的服务使用此类如

i want to use this in my service class like

public class service()
{
   *private IBaseRepository<T> _repo;

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

   public void MyMethod()
   {

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

}

因此,它的*标线,我想实现的,对此我不能。

So its the *marked lines i want to achieve, which i am unable to.

我使用温莎城堡为DI。

I am using castle windsor for DI.

感谢您的帮助球员

推荐答案

您不应该有其他除了您的通用接口库 IRepository< T> 。如果你需要的,你缺少的抽象。

You should not have other repository interfaces besides your generic IRepository<T>. If you need those, you are missing an abstraction.

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

For instance, a common reason for people to have custom repository interfaces is because they have a custom query that some repository has, while other don't. For instance:

public interface IEmployeeRepository : IRepository<Employee>
{
    Employee GetEmployeeOfTheMonth(int month);
}



这里的问题是, IEmployeeRepository 被滥用为自定义查询。自定义查询应该拥有自己的(通用)的抽象:

The problem here is that the IEmployeeRepository is abused for an 'custom query'. Custom queries deserve their own (generic) abstraction:

// 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> 衍生物:

With this abstraction we can add custom queries to the system, without the need of creating IRepository<T> derivatives:

public class GetEmployeeOfTheMonthQuery : IQuery<Employee>
{
    [Range(1, 12)]
    public int Month { get; set; }
}

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

这需要知道这个月的雇员一位消费者现在可以简单地采取 IQueryHandler℃的依赖; GetEmployeeOfTheMonthQuery,员工> 键,如下执行查询:

A consumer that needs to know the employee of the month, can now simply take a dependency on IQueryHandler<GetEmployeeOfTheMonthQuery, Employee> and execute the query as follows:

var query = new GetEmployeeOfTheMonthQuery { Month = 11 };
var employee = this.employeeOfMonthHandler.Handle(query);

这似乎是一个很大的开销,但这种模式是非常灵活的,可扩展的,并且有许多有趣特征。例如,它是很容易通过装饰包裹处理程序添加横切关注点。

This seems like a lot of overhead, but this model is very flexible, scalable, and has many interesting features. For instance, it is very easy to add cross-cutting concerns by wrapping handlers with decorators.

这也使得我们的reposities背后一个通用的接口被隐藏,这让我们。轻松批量立刻注册并添加装饰他们以及

This also allows our reposities to be hidden behind one generic interface, which allows us to easily batch register them at once and add decorators to them as well.

有关更深入的信息,请阅读这篇文章:的 ...同时在我的建筑的查询方。

For more in depth information, read this article: Meanwhile… on the query side of my architecture.

这篇关于泛型和DI存储库模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆