Raffaeu
Raffaeu

Reputation: 6973

IoC avoid to inject container

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

Answers (2)

Steven
Steven

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

Patrick Quirk
Patrick Quirk

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

Related Questions