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

本文关键字:转换 接口 泛型 实例 一个 | 更新日期: 2023-09-27 17:58:01

这是我的具体存储库,它派生自抽象基类

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)
 }

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

你想在这里做什么?我想不出在什么情况下你会想投IRepository<IPersistentBusinessObject>。什么代码依赖于什么抽象?

我通常希望其他代码依赖于IDepartmentRepository的抽象,而根本看不到IRepository<T>甚至IPersistentBusinessObject的用例。同样,如果你能找到一个依赖于抽象的代码用例,那么它们是有价值的;否则,YAGNI。

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


实际上,这是一个泛型类型的协方差问题。如果你说,它应该会起作用

public interface IRepository<out T> where T : IPersistantBusinessObject

您需要将其强制转换为IRepository<Department>

CCD_ 6源自实现CCD_ 8的CCD_。

你可能想看看方差和方差。。。

正如Daniel所暗示的,您不能将其强制转换为IRepository,因为您已将IRepositoryinterface定义为仅与另一种类型t一起存在。因此,作为接口的"IRepositori"是不存在的。

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

也许您需要两个接口,一个实现您在IRepository中想要的基本功能,另一个实现类型T的通用方法。例如

<!-- language: lang-c# -->
public interface IRepository
{
  SaveChanges()
...
}
public interface IRepositoryFor<T> where T : IPersistantBusinessObject
{
  T GetFirst(); // or whatever
...
}