I am trying to implement a command pattern with strongly typed input and output parameters for the command itself.
First of all I have created two interfaces that marks the input and the output for the command:
interface IRequest { }
interface IResponse { }
Then I have created the base classes and interfaces. This is the abstract receiver
interface IReceiver<TRequest, TResponse>
    where TRequest : IRequest
    where TResponse : IResponse
{
    TResponse Action( TRequest request );
}
and this the abstract command
abstract class AbstractCommand<TRequest, TResponse>
    where TRequest : IRequest
    where TResponse : IResponse
{
    protected IReceiver<TRequest, TResponse> _receiver;
    public AbstractCommand( IReceiver<TRequest, TResponse> receiver ) {
        _receiver = receiver;
    }
    public abstract TResponse Execute( TRequest request );
}
Now I am trying to use these objects and so I have created the needed concrete classes
class TypeARequest : IRequest
{
    public TypeARequest() {
    }
    public int NumericValueA { get; set; }
    public int NumericValueB { get; set; }
}
class TypeAResponse : IResponse
{
    public TypeAResponse() {
    }
    public int Result { get; set; }
}
class SumCommand : AbstractCommand<TypeARequest, TypeAResponse>
{
    public SumCommand( IReceiver<TypeARequest, TypeAResponse> receiver ) : base( receiver ) {
    }
    public override TypeAResponse Execute( TypeARequest request ) {
        return _receiver.Action( request );
    }
}
class SumReceiver : IReceiver<TypeARequest, TypeAResponse>
{
    public TypeAResponse Action( TypeARequest request ) {
        return new TypeAResponse() { Result = request.NumericValueA + request.NumericValueB };
    }
}
Finally I have created a CommandProcessor class which should be able to process multiple commands altogether
class CommandProcessor
{
    IList<AbstractCommand<IRequest, IResponse>> _supportedCommands = new List<AbstractCommand<IRequest, IResponse>>();
    public CommandProcessor() {
    }
    void AddSupportedCommand( AbstractCommand<IRequest, IResponse> item ) {
        _supportedCommands.Add( item );
    }
    void SetupSupportedCommands() {
        // ERROR HERE 
        AddSupportedCommand( new SumCommand( new SumReceiver() ) );
    }
}
However I am getting a compile time error saying:
Argument 1: cannot convert from 'SumCommand' to 'AbstractCommand'
Any help or suggestion?
You should create an interface and mark your generic parameter as covariance example:
interface IRequest { }
interface IResponse { }
interface IReceiver<in TRequest, out TResponse>
    where TRequest : IRequest
    where TResponse : IResponse
{
    TResponse Action(TRequest request);
}
interface ICommand<out TRequest, out TResponse>
{
}
abstract class AbstractCommand<TRequest, TResponse> : ICommand<TRequest, TResponse>
    where TRequest : IRequest   
    where TResponse : IResponse
{
    protected IReceiver<TRequest, TResponse> _receiver;
    public AbstractCommand(IReceiver<TRequest, TResponse> receiver)
    {
        _receiver = receiver;
    }
    public abstract TResponse Execute(TRequest request);
}
class CommandProcessor
{
    IList<ICommand<IRequest, IResponse>> _supportedCommands = new List<ICommand<IRequest, IResponse>>();
    public CommandProcessor()
    {
    }
    void AddSupportedCommand(ICommand<IRequest, IResponse> item)
    {
        _supportedCommands.Add(item);
    }
    void SetupSupportedCommands()
    {
        AddSupportedCommand(new SumCommand(new SumReceiver()));
    }
}
More information here out modifier msdn
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With