Enumeration with Generic Interface

Problem

I have commands to execute. Commands are plain C# classes with some data.

    var commands = new List<ICommand>
        {
            new Command1("A"),
            new Command1("B"),
            new Command2(20, 30)
        };

And I want to make command-specific handlers.

    public class Command1Handler : ICommandHandler<Command1>
    {
        public bool CanHandle(ICommand command)
        {
            return command is TCommand;      // this is always the same for all command handlers.
        }

        public void Execute(Command1 command)
        {
            // TODO: execute the command. I want to accept Command1, not ICommand.
        }
    }

And finally, I want to loop through commands and call corresponding commandHandlers.

    var commandHandlers = new List<ICommandHandler>()
        {
            new Command1Handler(),
            new Command2Handler()
        };

    foreach (var command in commands)
    {
        var handler = commandHandlers.Single(x => x.CanHandle(command));
        handler.Execute(command);
    }

C# does not allow such usage, since ICommandHandler<> cannot be used without <>. How do we solve this problem?

Solution

Define ICommandHandler as command-type-agnostic.

    public interface ICommandHandler
    {
        void Execute(ICommand command);
        bool CanHandle(ICommand command);
    }

Define CommandHandlerBase as generic class that accepts command-type T. It implements ICommandHandler, and it requires its child to implement abstract Execute(T command).

    public abstract class CommandHandlerBase<T>: ICommandHandler where T: ICommand
    {
        public bool CanHandle(ICommand command)
        {
            return command is T;
        }

        protected abstract void Execute(T command);

        public void Execute(ICommand command)
        {
            Execute((T)command);
        }
    }

Now command handler looks like:

    public class Command1Handler : CommandHandlerBase<Command1>
    {
        protected override void Execute(Command1 command)
        {
            // TODO: execute the command
        }
    }

Note that Command1Handler’s Execute() receives Command1, not ICommand.

Bonus: Command1Handler does not worry about CanHandle(), since by declaring CommandHandlerBase<Command1> I already said I can handle Command1 only.

Written on April 27, 2014