将具体类实例强制转换为使用泛型的接口

时间:2011-05-31 22:20:26

标签: c# generics interface casting

这是我从具体抽象基类派生的具体存储库

public class DepartmentRepository : RepositoryBase<Department>, IDepartmentRepository

public abstract class RepositoryBase<T> : IRepository<T> where T : class, IPersistantBusinessObject

这是我的界面

public interface IDepartmentRepository : IRepository<Department>

public interface IRepository<T> where T : IPersistantBusinessObject

public interface IPersistantBusinessObject { ... }

这是我的实体

public class Department : BusinessObjectBase

public abstract class BusinessObjectBase : IPersistantBusinessObject

如何将我的DepartmentRepository转换为通用IRepository?

DepartmentRepository rep = new DepartmentRepository();
(IRepository<IPersistentBusinessObject>)rep; // this doesn't work

想法?如果你想知道,这是一个使用存储库模式的asp.net MVC3应用程序。我是否过度构建接口?我现在想如何使用通用存储库?

感谢。

编辑: 这是我的IRepository界面。当被问及为什么我需要转换为IRepository时,实际上我只能使用“SaveChanges”方法,因为我想拦截数据库中的任何异常并以通用方式处理。

public interface IRepository<T> where T: IPersistantBusinessObject
{
    IQueryable<T> Retrieve();
    T Retrieve(int id);
    IQueryable<T> RetrieveActiveAndInActive();
    T RetrieveActiveAndInActive(int id);
    void Add(T domainObject);
    void SaveChanges();
    void Delete(T domainObject);
    void Delete(int id)
 }

3 个答案:

答案 0 :(得分:3)

你想在这做什么?我想不出你想要投射到IRepository<IPersistentBusinessObject>的情况。什么代码依赖于什么抽象?

我通常希望其他代码依赖于IDepartmentRepository的抽象,并且根本无法真正看到IRepository<T>甚至IPersistentBusinessObject的用例。同样,如果您可以找到依赖于该抽象的代码的用例,那么它们是有价值的;否则,YAGNI

(顺便说一句,这是测试驱动开发很有价值的一个原因。你可以通过编写单元测试来确定需要哪些抽象,并查看需要模拟哪些类来隔离某些功能的测试,而不是只是模糊地将所有东西抽象成接口,因为你被告知它们比具体类型更好。从具体类型开始,当你的测试强制你提取界面时,那是正确的时间!)


但实际上,这是covariance of generic types的问题。如果你说

,它应该有效
public interface IRepository<out T> where T : IPersistantBusinessObject

答案 1 :(得分:0)

您需要将其投射到IRepository<Department>

DepartmentRepository派生自实现RepositoryBase<Department>的{​​{1}}。

您可能需要查看co and contravariance ...

答案 2 :(得分:0)

正如Daniel暗示的那样,你不能把它强制转换为IRepository,因为你已经将IRepository接口定义为只与另一个类型T一起存在。所以“IRepository”作为接口不存在。

如果您希望能够使用“IRepository”接口,那么它需要是一个没有类型依赖的独立接口。

也许您需要两个接口,一个用于实现IRepository中所需的基本功能,另一个用于实现类型T的泛型方法。 e.g。

<!-- language: lang-c# -->
public interface IRepository
{
  SaveChanges()
...
}

public interface IRepositoryFor<T> where T : IPersistantBusinessObject
{
  T GetFirst(); // or whatever
...
}