I've been using a pattern very similar to what is described in this excellent article to have commands and queries as objects. I am also using SimpleInjector as the DI container.
The only significant difference is that rather that controller take an explicit dependency on some ICommandHandler<TCommand>
I want the controllers to take a dependency on an object (a Dispatcher
) which will take a ICommand
instance and resolve the correct handler for that command. This will reduce the number of parameters that the constructors need to take and make the whole thing a little easier to use.
So my Dispatcher
objects constructor looks like this:
public CommandAndQueryDispatcher(IEnumerable<ICommandHandler> commandHandlers,
IEnumerable<IQueryHandler> queryHandlers)
{
}
and my CommandHandler interfaces look like this:
public interface ICommandHandler<in TCommand> : ICommandHandler
where TCommand : ICommand
{
void Execute(TCommand command, ICommandAndQueryDispatcher dispatcher);
}
public interface ICommandHandler
{
void Execute(object command, ICommandAndQueryDispatcher dispatcher);
}
And a typical command handler looks like:
public abstract class CommandHandlerBase<TCommand> : ICommandHandler<TCommand>
where TCommand : ICommand
{
public abstract void Execute(TCommand command, ICommandAndQueryDispatcher dispatcher);
public void Execute(object command, ICommandAndQueryDispatcher dispatcher)
{
Execute((TCommand) command, dispatcher);
}
}
internal class DeleteTeamCommandHandler : CommandHandlerBase<DeleteTeamCommand>
{
public DeleteTeamCommandHandler(){ }
public override void Execute(DeleteTeamCommand command,
ICommandAndQueryDispatcher dispatcher)
{
... functionality here...
}
}
However this change had some knockons and now I want to add some decorators to my commands and queries I've having some problems.
In order to have all of the commands and queries injected into the Dispatcher
I made them all have a base, genericless, interface ICommandHandler
and IQueryHandler
, then interrogate the instances actually received (which are generic) to get the type of command they handle to register them so I can look up the handler based on the type of the given command later on.
Now when I try and use decorators as indicated in the examples I can't seem to get anything injected into my Dispatcher
, as the decorated instances are registered as generic types, so don't get resolved as basic ICommandHandler
instances. If I try making the decorators non generic then the instances which are injected don't have any generic type parameters so I can't find what type of command its a handler for.
I feel like I must be missing something fairly simple.
So my question is either
- How can I get all instances of an open generic type from the container cast as a base interface passed into my
Dispatcher
?
OR
- Is there a better way for me to implement the dispatcher functionality so that my controllers can be ignorant of which handler is going to handle a command/query which plays more nicely with SimpleInjector?
Please take a close watch on this, because by doing this, you might hide the fact that your controllers do too much; violate the Single Responsibility Principle. SRP violations tend to lead to maintainability issues later on. There's even a follow up article of the author of the article you refer to (that's me btw) that states:
The article even discusses a solution for this for queries, but you can apply it to your commands as well. But you should consider stripping your solution down and remove the non-generic interfaces. You don't need them.
Instead, define the following:
Do note a few things:
ICommandAndQueryDispatcher
. That's just ugly. TheICommandAndQueryDispatcher
is a service and services need to be passed through constructor injection. Thecommand
on the other hand is runtime data, and runtime data is passed through using method arguments. So if there's a command or query handler that needs the dispatcher: inject it through the constructor.in
keyword forTCommand
. Since commands are use cases, there should be a one-to-one mapping between a command and a command handler implementation. Specifying an 'in' however means that one command class can map to multiple handlers, but this should not be the case. When dealing with events and event handlers on the other hand, this will be a much more obvious approach.CommandHandlerBase<TCommand>
. You don't need that. I would argue that a good design hardly ever needs a base class.Another thing, don't try to mix the dispatcher for commands with that for the queries. Two responsibilities means two classes. This is how your command dispatcher will look:
Do note that you don't inject a collection of command handlers here, but instead to request a handler from the container. This code will only contain infrastructure and no business logic, so if you place this implementation close to the code that is responsible of wiring the container, you will not abuse the Service Locator anti-pattern, and this is a valid approach. The rest of the application in that case still doesn't depend on the DI framework.
You can register this
CommandDispatcher
as follows:If you take this approach, because you request a handler by the
ICommandHandler<TCommand>
interface, the container will automatically wrap the handlers with any decorators that must be applied according to your configuration and the generic type constraints you applied.