Your commands (Command1
and Command2
) are not services: they should not be registered. They are runtime data (message) that you pass through your services (your command handlers). So you should remove the Collection.Register<ICommand>
(RegisterAll
in v2) registration. It is of no use. You already see its of no use, since in your example you are newing the Command2
up manually, which is the right thing to do.
What you are doing in the last three lines of code is dispatching a command of an unknown type to the right command handler registration. You always need some reflection to pull this of, since you need to build the closed ICommandHandler<TCommand>
type based on the command type, which is something you don't know at compile time. Instead of using the C# dynamic
keyword, you can also use the .NET reflection API, but in my experience using dynamic
is better in this particular case. One important downside of the reflection API is that the API will always wrap any thrown exception (in case of a failure) with an InvocationException
and that makes it harder to do certain exception handling up the call stack.
So long story short, this should be your registration:
Container container = new Container();
container.Register(
typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CommandDecorator<>));
And this should be the dispatching logic:
var type = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = container.GetInstance(type);
handler.Execute((dynamic)command);