C#泛型是关键字协方差/逆变式推断 请考虑此接口: public interface IInitialiazableEntity<TRepository> where TRepository : class, IRepository { void Initialize(TRepository repository); } 公共接口IIInitializableEntity,其中TRepository:class,IRepository { 作废初始化(存储库); }

C#泛型是关键字协方差/逆变式推断 请考虑此接口: public interface IInitialiazableEntity<TRepository> where TRepository : class, IRepository { void Initialize(TRepository repository); } 公共接口IIInitializableEntity,其中TRepository:class,IRepository { 作废初始化(存储库); },c#,generics,covariance,contravariance,C#,Generics,Covariance,Contravariance,此类(代码段): public类,其中TRepository:class,IRepository { public void Add(tenty实体),其中tenty:AbstractEntity { 尝试 { if(实体为IInitializableEntity) (实体为IIInitializableEntity)。初始化(this.Repository); } 捕获(例外情况除外) { 此.Logger.Error(ex); } } } 以及该实体: public class Stude

此类(代码段):

public类,其中TRepository:class,IRepository
{
public void Add(tenty实体),其中tenty:AbstractEntity
{
尝试
{
if(实体为IInitializableEntity)
(实体为IIInitializableEntity)。初始化(this.Repository);
}
捕获(例外情况除外)
{
此.Logger.Error(ex);
}
}
}
以及该实体:

public class Student : AbstractEntity, IInitialiazableEntity<IRepository>
{ 
    void Initialize(IRepository repository) { ... }
}
公共类学生:AbstractEntity,IInitialAzableEntity
{ 
无效初始化(IRepository存储库){…}
}

由于学生仅为
iInitializableEntity
,门面将有一个比基本
IRepository
更专业的实际存储库(即它将是
IMySpecialRepository:IRepository
),
is
关键字是否会意识到它可以强制转换
IMySpecialRepository
,并将其传递给实体的
Initialize
方法?或者如果不是,怎么做?

假设您的实体是Student类型,“is”将返回false;这是因为Student没有实现更具体的接口专门化。不过,您不需要强制转换到这个更具体的接口。这应该很好:

public class SomeFacade<TRepository> where TRepository : class, IRepository
{
        public void Add<TEntity>(TEntity entity) where TEntity : AbstractEntity
        {
            try
            {
                if (entity is IInitialiazableEntity<IRepository>)
                    (entity as IInitialiazableEntity<IRepository>).Initialize(this.Repository);
            }
            catch (Exception ex)
            {
                this.Logger.Error(ex);
            }
        }
}
public类,其中TRepository:class,IRepository
{
public void Add(tenty实体),其中tenty:AbstractEntity
{
尝试
{
if(实体为IInitializableEntity)
(实体为IIInitializableEntity)。初始化(this.Repository);
}
捕获(例外情况除外)
{
此.Logger.Error(ex);
}
}
}

当前,如果您有一个实例
SomeFacade
代码将无法工作

你有两个选择,一个是Dan Bryant提供的答案,另一个是使
iInitializableEntity
逆变

您的接口声明将变为(注意泛型类型上中的
):

公共接口IIInitializableEntity,其中TRepository:class,IRepository
{
作废初始化(存储库);
}
这将允许您的
is
检查和转换工作,因为当使用逆变泛型时,
IInitializableEntity
可以转换为
IInitializableEntity


有关泛型中协方差和逆变换的更多信息,请参阅。

您尝试过吗?还有,什么是IMySpecialRepository和IMYSpecialedRepository?很抱歉,我知道我可以测试一下,然后尝试找到解决方案,但我现在特别忙。我认为它对其他人也会很有用(因为标题/标签是正确的)。@ken2k特殊(化)存储库(有一个拼写错误,两者都是一样的,我更正了它)-是从基础IRepository继承的任何东西。当然你可以做到。问题是,你应该吗?实际的类型应该与您无关。但是学生实体可能会使用基本IRepository,而其他实体可能会使用更专门的存储库实现iInitializableEntity,因此我需要支持它。但是继承的顶部将是facade拥有的TRepository。没有实体会使用比门面更专业的回购协议。或者我可以让实体必须用最专门的回购协议来实现初始化,然后用它来完成,那么is将返回true。。你觉得呢?谢谢你,先生,这一个让一切都不同了。如果不是我问的话,我永远不会走这条路。谢谢分享。
public class SomeFacade<TRepository> where TRepository : class, IRepository
{
        public void Add<TEntity>(TEntity entity) where TEntity : AbstractEntity
        {
            try
            {
                if (entity is IInitialiazableEntity<IRepository>)
                    (entity as IInitialiazableEntity<IRepository>).Initialize(this.Repository);
            }
            catch (Exception ex)
            {
                this.Logger.Error(ex);
            }
        }
}
public interface IInitialiazableEntity<in TRepository> where TRepository : class, IRepository
{
    void Initialize(TRepository repository);
}