Monday, February 11, 2013

A Better Dispatcher with the Factory Facility

In the applications we write, we often use the same principles. First off, there is dependency injection, preferably through the constructor of a class. Second we often use CQS, to get a clear separation between the commands and queries of our application.

For implementing CQS we often utilize some kind of a dispatcher. This is a simple class which has Dispatch methods for commands and queries. We can use it like so:

public class DoubleAddressController : Controller
{
    readonly IDispatcher _dispatcher;

    public DoubleAddressController(IDispatcher dispatcher)
    {
        _dispatcher = dispatcher;
    }

    public ActionResult GetExistingFilesForAddress(FindDoubleAddressRequest request)
    {
        var result = _dispatcher.DispatchQuery<FindDoubleAddressRequest, FindDoubleAddressResponse>(request);
        return PartialView(result);
    }
}


We ask the dispatcher to dispatch a query for a certain request and response. I ommitted error handling and additional mapping from the above example.

So, the dispatcher gets a certain command or query as an argument and based on this needs to ask a certain query or commandhandler to handle this command or query. Up untill now I used the IoC repository to get hold of this queryhandler:

public class Dispatcher : IDispatcher
{
    readonly IWindsorContainer _windsorContainer;

    public Dispatcher(IWindsorContainer windsorContainer)
    {
        _windsorContainer = windsorContainer;
    }

    public TResponse DispatchQuery<TRequest, TResponse>(TRequest request)
    {
        var handler = _windsorContainer.Resolve<IQueryHandler<TRequest, TResponse>>();

        if (handler == null)
            throw new ArgumentException(string.Format("No handler found for handling {0} and {1}", typeof(TRequest).Name, typeof(TResponse).Name));

        try
        {
            return handler.Handle(request);
        }
        finally
        {
            _windsorContainer.Release(handler);
        }
    }
}

The dispatcher has a dependency on our IoC container, in the example above a WindsorContainer, and asks this container to get hold of the specific handler that can handle the request we just got in.

With this solution however there are a couple of problems. First of all, we need a dependency on our IoC container (in the IoC configuration we configure the container with a reference to itself). Second, we resolve a dependency from the container, which is just not done (service location is known as an anti-pattern). And we need to think about releasing the handler dependency we just resolved. Something the developer needs to think about and which I've seen forgotten.

So, there should be a better solution for this, and there is! I recently started a refactor on another piece of code which used a factory to get hold of instances and which did not make use of our Castle Windsor container. I started looking at the Castle Windsor documentation and you can actually configure it with classes which act as factory and with a factory facility. After this refactoring I thought this factory facility might as well be usable for our not so ideal dispatcher.

First we got rid of the WindsorContainer dependency in the dispatcher:

public class Dispatcher : IDispatcher
{
    private readonly IFindHandlersFactory _handlerFactory;

    public Dispatcher(IFindHandlersFactory handlerFactory)
    {
        _handlerFactory = handlerFactory;
    }

    public TResult Dispatch<TRequest, TResult>(TRequest request)
    {
        var handler = _handlerFactory.CreateFor<TRequest, TResult>(request);
        if (handler == null)
            throw new HandlerNotFoundException(typeof(IQueryHandler<TRequest, TResult>));
        
        return handler.Handle(request);
    }
}


We now use a IFindHandlersFactory. A factory which just finds handlers for us. This interface just has one method defined, CreateFor, with generic type parameters. The thing is that we will not make an implementation for this interface. This interface will be configured in our Castle Windsor container as a factory.


container.AddFacility<typedfactoryfacility>();

container
    .Register(
        Component
            .For<IDispatcher>()
            .ImplementedBy<Dispatcher>()
            .LifestyleTransient())
    .Register(
        Component
            .For<IHandlerFactory>()
            .AsFactory()
            .LifestyleTransient())
    ;

Once you have done this, Castle Windsor will automatically resolve your handlers, without you having to actually call Resolve for these dependencies.

No comments:

Post a Comment