2009-10-15 39 views
0

我是新來的泛型實現,需要在2個問題我輸入面對具有約束的通用方法的接口的通用類:如何編寫實現定義

我有一個接口的ICommand定義爲:

public ICommand 
{ 
    List<T> Execute<T>() where T : IValidationResult; 
    IDomain<T> GetDO<T>() where T : IValidationResult; 

} 

有意將它作爲非泛型,因爲我必須添加不同命令的集合。

這個界面我希望在一個名爲PersistCommand作爲一個通用類來實現:

public PersistCommand<TDomainObj,T> : ICommand where TDomainObj : IDomain<T> where T : IValidationResult 
{ 
     private TDomainObj _domainObject;//IDomain<T> is an interface 

     public PersistCommand(TDomainObj TDomainObject) 
     { 
      _domainObject = TDomainObject; 

     } 

     public IDomain<T> GetDO<T>() where T : IValidationResult 
     { 
      return _domainObject as IDomain<T>; 
     } 

     public List<T> Execute<T>() where T : IValidationResult 
     { 
      //returns a list<T> 
     } 
} 

有一個泛型類背後的意圖是從類通過這些約束不幸的是不會發生這些泛型方法(不知道爲什麼?編譯時,我得到一個警告:類型參數'T'具有與來自外部類型'PersistCommand'的類型參數相同的名稱這是第一個問題。

第二個問題是: 我有不同組的命令,從中繼承的InsertCommand,DeleteCommand和UpdateCommand PersistCommand並在單獨調用Execute()方法時正常工作。

我有一個是用於多個命令的執行如圖所示的命令管理類:

public class CommandManager 
    { 

     public virtual IEnumerable<T> Perform<T>(List<ICommand> commandList) 
      where T : IValidationResult 
     { 
      List<T> validationResults = new List<T>(); 

      //fire pre-intent validations 
      foreach (ICommand command in commandList) 
      { 
       validationResults.AddRange(command.GetDomainObject<T>().Validate(command.GetPreIntent())); 
      } 

      //fire intent validations 
      if (validationResults.Count == 0) 
      { 
       foreach (ICommand command in commandList) 
       { 
        validationResults.AddRange(command.Execute<T>()); 
       } 
      } 

      //fire post-intent validations 
      if (validationResults.Count == 0) 
      { 
       foreach (ICommand command in commandList) 
       { 
        validationResults.AddRange(command.GetDomainObject<T>().Validate(command.GetPostIntent())); 
       } 
      } 

      return validationResults; 
     } 

    } 

只要傳遞給命令和所述CommandManager.Perform方法的類型「T」是相同的,有用。 但是我有一種情況,其中,我們有具有不同「T」作爲類型2個域對象:

class Project : IDomain<CustomResult>//CustomResult implements IValidationResult 
class Resource : IDomain<AnotherResult>//AnotherResult implements IValidationResult 

當我打電話CommandManager.Perform(commandList)它拋出在

異常

GetDO方法示出的消息:對象引用未設置到對象」

任何幫助或想法的一個實例來解決這個問題,將不勝感激

回答

2

第一個問題,從事實OU莖聲明的泛型類型T我。 n方法定義,而不是整體接口定義。

因此,要獲得它來編譯你不得不改變接口和類定義:

public interface ICommand<T> where T : IValidationResult 
{ 
    List<T> Execute(); 
    IDomain<T> GetDO(); 
} 

public class PersistCommand<TDomainObj,T> : ICommand<T> where TDomainObj : IDomain<T> where T : IValidationResult<T> 
{ 
    private TDomainObj _domainObject;//IDomain<T> is an interface 

    public PersistCommand(TDomainObj TDomainObject) 
    { 
     _domainObject = TDomainObject; 
    } 

    public IDomain<T> GetDO() 
    { 
     return _domainObject as IDomain<T>; 
    } 

    public List<T> Execute() 
    { 
     //returns a list<T> 
    } 
} 

你也可以聲明在實現類中的方法是使用名爲大於T以外的東西泛型類型,但這隻會增加更多的複雜性。

但是,我認爲這一切都被更廣泛的問題所淹沒 - 您似乎在嘗試使用類似接口的泛型。

從代碼示例,只要它看起來並不像您一定需要使用,你是仿製藥多,而且認爲它只是使問題複雜

我想嘗試簡化了下去:

public interface ICommand 
{ 
    List<IValidationResult> Execute(); 
    IDomain<IValidationResult> GetDO(); 
} 

public class PersistCommand<TDomainObj> : ICommand where TDomainObj : IDomain<IValidationResult> 
{ 
    private TDomainObj _domainObject;// 

    public PersistCommand(TDomainObj TDomainObject) 
    { 
     _domainObject = TDomainObject; 

    } 

    public IDomain<IValidationResult> GetDO() 
    { 
     return _domainObject; 
    } 

    public List<IValidationResult> Execute() 
    { 
     //returns a list<T> 
    } 
} 

public class CommandManager 
{ 

    public virtual IEnumerable<IValidationResult> Perform(List<ICommand> commandList) 
    { 
     List<IValidationResult> validationResults = new List<IValidationResult>(); 

     //fire pre-intent validations 
     foreach (ICommand command in commandList) 
     { 
      validationResults.AddRange(command.GetDO().Validate(command.GetPreIntent())); 
     } 

     //fire intent validations 
     if (validationResults.Count == 0) 
     { 
      foreach (ICommand command in commandList) 
      { 
       validationResults.AddRange(command.Execute()); 
      } 
     } 

     //fire post-intent validations 
     if (validationResults.Count == 0) 
     { 
      foreach (ICommand command in commandList) 
      { 
       validationResults.AddRange(command.GetDO().Validate(command.GetPostIntent())); 
      } 
     } 

     return validationResults; 
    } 

} 

這樣你就可以看到所有相同的東西(例如通過界面),它看起來就像你正在做的那樣。你唯一使用泛型的方法是在PersistCommand中指定域對象的特定類型,我認爲你可能需要內部使用或子分類。

+0

喜戴夫, 我試過了,但它並沒有編譯和得到的錯誤信息: PersistCommand 「不實現接口成員」 ICommand.GetDO () – Chandrasekhar 2009-10-15 13:54:59

+0

我已經更新我的回答覆蓋了這一點,這與你如何聲明你的界面有關。我還添加了一些關於簡化整個事情的部分... HTH – 2009-10-15 14:34:01