I'm new to Generics implementation and need inputs on 2 issues I face :
I have an interface ICommand defined as :
public ICommand
{
List<T> Execute<T>() where T : IValidationResult;
IDomain<T> GetDO<T>() where T : IValidationResult;
}
intentionally I have it as non-generic as I have to add a collection of different commands.
This interface I wish to implement in a generic class called PersistCommand as :
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>
}
}
The intention behind having a generic class is to pass these constraints from the class to these generic methods which unfortunately doesn't happen(Not sure why? when compiled ,I get a warning:Type parameter 'T' has the same name as the type parameter from outer type 'PersistCommand' This is the first issue.
The second issue is : I have different set of commands,InsertCommand,DeleteCommand and UpdateCommand that inherit from the PersistCommand and work fine when the Execute() method is called individually.
I have a CommandManager class that is used for execution of multiple commands as shown :
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;
}
}
As long as the type "T" that is passed to the Commands and the CommandManager.Perform method are same,it works. But I have a scenario wherein we have 2 Domain objects having different "T" types as :
class Project : IDomain<CustomResult>//CustomResult implements IValidationResult
class Resource : IDomain<AnotherResult>//AnotherResult implements IValidationResult
When I call CommandManager.Perform(commandList) it throws an exception at
GetDO method showing a message:Object reference not set to an instance of the object"
Any help or ideas to solve this would be appreciated.