2014-11-03 61 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