Reputation: 6973
I am working with IoC and more precisely with windsor and I have an amletic doubt about one thing. Right now I am implementing the DDD Command layer so for each command I have a concrete class as following
public class CreateUserCommand : IDomainCommand{
/// implementation
}
Each command has 1 or more handlers with the following implementation
public class CreateUserHandler : IDomainCommandHandler<CreateUserCommand>
{
public void Handle(CreateUserCommand command)
{
/// implementation
}
}
The problem arise with my Command Dispatcher. I am using the following form at the moment
public class CommandDispatcher : ICommandDispatcher
{
private IWindsorContainer container;
public CommandDispatcher(IWindsorContainer container)
{
this.container = container;
}
public void Dispatch<T>(T command)
{
var commandHandler = container.Resolve<ICommandHandler<T>>();
commandHandler.Handle(command);
}
}
What I don't like is the awareness of the dispatcher about the IoC container but in the same way I don't know how I can sort of resolve the handlers only when I need them. Shell I inject an handler factory inside the Dispatcher and use it to resolve my handlers at runtime?
Upvotes: 2
Views: 296
Reputation: 172646
It's okay for infrastructure code that is part of your composition root to take a dependency on the container. This is not an implementation of the Service Locator anti-pattern, since the Service Locator is about role and not mechanics.
In other words, as long as your CommandDispatcher
is part of the composition root (and contains just infrastructure, no business logic) it is okay to let it depend on the container.
Upvotes: 2
Reputation: 23747
I'd use the typed factory facility to create a factory to replace the container usage. Conceptually the idea is the same, but it removes the dependency on the container.
The factory (no implementation, the facility takes care of that):
public interface ICommandHandlerFactory
{
ICommandHandler<T> Create<T>();
}
Registration:
// requires Castle.Facilities.TypedFactory namespace
windsorContainer.AddFacility<TypedFactoryFacility>();
// AsFactory() is an extension method in the same namespace
windsorContainer.Register(Component.For<ICommandHandlerFactory>().AsFactory());
Then in your class:
public class CommandDispatcher : ICommandDispatcher
{
private ICommandHandlerFactory commandHandlerFactory;
public CommandDispatcher(ICommandHandlerFactory commandHandlerFactory)
{
this.commandHandlerFactory = commandHandlerFactory;
}
public void Dispatch<T>(T command)
{
var commandHandler = commandHandlerFactory.Create<T>();
commandHandler.Handle(command);
}
}
Upvotes: 7