2014-11-03 103 views
0

请考虑这个接口:C#泛型是关键字协方差/逆变式inferral

public interface IInitialiazableEntity<TRepository> where TRepository : class, IRepository 
{ 
    void Initialize(TRepository repository); 
} 

这个类(片段):

public class SomeFacade<TRepository> where TRepository : class, IRepository 
{ 
     public void Add<TEntity>(TEntity entity) where TEntity : AbstractEntity 
     { 
      try 
      { 
       if (entity is IInitialiazableEntity<TRepository>) 
        (entity as IInitialiazableEntity<TRepository>).Initialize(this.Repository); 
      } 
      catch (Exception ex) 
      { 
       this.Logger.Error(ex); 
      } 
     } 
} 

与实体:

public class Student : AbstractEntity, IInitialiazableEntity<IRepository> 
{ 
    void Initialize(IRepository repository) { ... } 
} 

由于学生只有IInitialiazableEntity<IRepository>和门面将有一个比t更专业的实际储存库他基本上是IRepository(即它将是IMySpecialRepository : IRepository),is关键字会意识到它可以将IMySpecialRepository强制转换为实体的Initialize方法?或者如果不是,该怎么做?

+0

你试过了吗?此外,什么是IMySpecialRepository和IMySpecializedRepository? – ken2k 2014-11-03 13:42:02

+0

对不起,我知道我可以测试这个,然后尝试找到一个解决方案,但我很匆忙。我认为这对其他人很有用(因为标题/标签是正确的)。 – 2014-11-03 13:45:28

+0

@ ken2k特殊(ized)存储库(有一个错字,两者是相同的,我纠正了它) - 是从基本IRepository继承的任何东西。 – 2014-11-03 13:47:22

回答

1

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

你有两个选择,一个是Dan Bryant提供的答案,另一个是使IInitialiazableEntity<TRepository>逆变。

您接口声明将成为(注意泛型类型的in):

public interface IInitialiazableEntity<in TRepository> where TRepository : class, IRepository 
{ 
    void Initialize(TRepository repository); 
} 

这将使你的is检查,并转换为工作,为IInitialiazableEntity<IRepository>可以使用逆变通用时被转换为IInitialiazableEntity<IMySpecialRepository>

请参阅here了解更多关于泛型和协变性的信息。

+0

谢谢,先生,一个在所有区别。我没有问过,我从来不会这样去。感谢分享。 – 2014-11-03 14:10:36

1

假设您的实体是Student类型,'is'将返回false;这是因为学生没有实现更具体的接口专业化。不过,您不需要投射到更具体的界面。这应该工作得很好:

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); 
      } 
     } 
} 
+0

但是学生实体可能会使用基本的IRepository,而其他实体可能会使用更专门的存储库来实现IInitialiazableEntity,因此我需要支持它。 – 2014-11-03 13:49:12

+0

但是,继承的顶部将是门面所具有的TRepository。没有实体会使用比立面更专业的回购。或者我可以让实体必须用最专业的回购来实现可初始化,并且用它来完成,然后该回归将是真的。您怎么看? – 2014-11-03 13:51:05