I have the following:
public interface ICommand { }
public class AddUser : ICommand
{
public string Name { get; set; }
public string Password { get; set; }
}
public interface ICommandHandler<T> : IHandler<T> where T : ICommand
{
void Execute(T command);
}
public class AddUserHandler : ICommandHandler<AddUser>
{
public void Execute(AddUser command)
{
Console.WriteLine("{0}: User added: {1}", GetType().Name, command.Name);
}
}
public class AuditTrailHandler : ICommandHandler<ICommand>
{
public void Execute(ICommand command)
{
Console.WriteLine("{0}: Have seen a command of type {1}", GetType().Name, command.GetType().Name);
}
}
I would like to use scanning to register the ICommandHandler<> so that I get the following types in the container:
ICommandHandler<AddUser>with concrete typeAddUserHandlerICommandHandler<AddUser>with concrete typeAuditTrailHandler
I have tried this with an implementation of IRegistrationConvention and at one point I had it working but I just cannot get my head around how I did it.
The goal is to be able to execute several handlers for a specific ICommand implementation like so:
// A method in CommandDispatcher
public void SendCommand<T>(T command) where T : ICommand {
var commandHandlers = container.GetAllInstances<ICommandHandler<T>>();
foreach (var commandHandler in commandHandlers) {
commandHandler.Execute(command);
}
}
I want the AuditTrailHandler<ICommand> to execute for all concrete implementations of ICommand, hence the need to register them for all types of ICommand.
Secondary objective would be if I could inject a collection of ICommandHandlers<ICommand> into my CommandDispatcher instead of the container, but I think that's impossible with the structure I have now. Prove me wrong if you have any ideas.
EDIT - solved
I added a non generic interface that my generic interface implements and then I also added an Abstract CommandHandler<T> so I don't have to implement the CanHandle or Execute(object) methods in all my handlers.
This is the working structure:
public interface ICommandHandler
{
void Execute(object command);
bool CanHandle(ICommand command);
}
public interface ICommandHandler<T> : ICommandHandler, IHandler<T> where T : ICommand
{
void Execute(T command);
}
public abstract class AbstractCommandHandler<T> : ICommandHandler<T> where T : ICommand
{
public abstract void Execute(T command);
public void Execute(object command)
{
Execute((T)command);
}
public virtual bool CanHandle(ICommand command)
{
return command is T;
}
}
And since this originally was a StructureMap question, here is the Scan to add this:
Scan(x =>
{
x.AssemblyContainingType<MyConcreteHandler>();
x.IncludeNamespaceContainingType<MyConcreteHandler>();
x.AddAllTypesOf<ICommandHandler>();
x.WithDefaultConventions();
});
This makes me able to inject an IEnumerable in my CommandDispatcher and execute like so:
public void SendCommand<T>(T command) where T : ICommand
{
var commandHandlersThatCanHandle = commandHandlers.Where(c => c.CanHandle(command));
foreach (var commandHandler in commandHandlersThatCanHandle)
{
commandHandler.Execute(command);
}
}
This makes me able to execute CommandHandlers that support AddUser (like the AddUserHandler), but I'm also able to execute a handler that support ICommand (like the AuditTrailHandler).
This is sweet!