2009-10-15 34 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