0

假设我有一个通用数据访问层,它应该支持不同的实现。为了实现这一点,我有一个基本接口IPeristenceService,它定义了访问持久层内数据的所有方法。界面可能如下所示:

public interface IPersistence
{
    TData GetData<TData, TKey>(TKey Key);
}

所以持久化服务不能创建仅由它们的接口定义的对象的实例,所以限制 - 方法的实现是一个不错的决定GetData

public interface IPersistence
{
    TData GetData<TData, TKey>(TKey Key) where TData : class, new();
}

这非常简单,因为实现此接口的开发人员在尝试返回接口指针时将无法编译他们的代码。持久层内部的数据需要用实现的对象来表示,而不是接口!

现在假设我们正在创建一个持久化服务,它将数据持久化到一个关系数据库中,由实体表示。所有实体都继承自一个基本接口:IEntity. 传递非实体对象一定会失败,因为持久化服务只能持久化实体。所以我们需要验证传递的对象实例是否继承自IEntity. 在编译时使用 where-notation 是可能的,但只需实现这样的接口:

public class DbPersistence : IPersistence
{
    public TData IPersistence.GetData<TData, TKey>(TKey Key)
        where TData : IEntity, class, new();
    {
        // fancy data access code
    }
}

不工作,是吗?!

有什么办法可以实现我想要做什么?

先感谢您 :-)

4

1 回答 1

4

类型约束TData继承自您正在实现的接口方法,这就是为什么无法在实现上修改它们的原因。我能想到两种典型的解决方案:

IEntity约束向上移动到接口定义

public interface IPersistence
{
    TData GetData<TData, TKey>(TKey Key) where TData : class, IEntity, new();
}

这在很多情况下都是合适的,因为所有持久对象之间的一定数量的共同点既合理又合乎需要。

显式实现原始接口并公开实现专用接口

public interface IPersistence
{
    TData GetData<TData, TKey>(TKey Key) where TData : class, new();
}

public interface IDbPersistence
{
    TData GetData<TData, TKey>(TKey Key) where TData : class, IEntity, new();
}

public class DbPersistence : IPersistence, IDbPersistence
{
    TData IPersistence.GetData<TData, TKey>(TKey Key)
    {
        // fancy data access code
    }

    TData GetData<TData, TKey>(TKey Key)
    {
        return ((IPersistence)this).GetData<TData, TKey>(Key);
    }
}

通过这种方式,您可以将自定义持久层用作更丰富的指定IDbPersistence,同时保持与数据访问层中仅知道IPersistence.

于 2012-07-10T10:03:05.887 回答