1

我有一个其他合同扩展的基本存储库合同,如下所示

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

然后还有其他合同将其扩展如下

public interface IRepository1 : IBaseRepository<MyClass1>
{
}

public interface IRepository2 : IBaseRepository<MyClass2>
{
}

我实现 IRepository1 如下

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

对于 IRepository2 类似

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

现在我有一个服务 Service1 实现 IService 如下

public class Service1 : IService
{


}

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

 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

我想在我的服务类中使用它

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

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

   public void MyMethod()
   {

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

}

所以它是我想要实现的*标记线,我无法做到。

我正在为 DI 使用城堡温莎。

谢谢你们的帮助

4

2 回答 2

8

除了通用的IRepository<T>. 如果你需要这些,你就错过了一个抽象。

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

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

这里的问题是IEmployeeRepository被滥用于“自定义查询”。自定义查询值得拥有自己的(通用)抽象:

// 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>派生词:

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>并执行查询,如下所示:

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

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

这也允许我们的存储库隐藏在一个通用接口之后,这使我们能够轻松地一次批量注册它们并向它们添加装饰器。

有关更深入的信息,请阅读这篇文章:同时……在我的架构的查询方面

于 2012-10-16T15:16:48.790 回答
0

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

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

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

   public void MyMethod()
   {

      var x = _repo.MethodFromIBaseRepository()
   }

}
于 2012-10-16T05:34:33.283 回答