Type error in command pattern

104 views Asked by At

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?

1

There are 1 answers

7
Alcruz On BEST ANSWER

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