Advanced StructureMap: connecting implementations to open generic types


One pattern we’re starting to see more and more is the idea of connecting messages to handlers.  These messages might be domain command messages, ActionResult messages, and more.  Beyond messaging implementations, we start to see a more basic pattern start to emerge.  We have some interface describing a contract that happens to be generic:

public interface IFooService<T>
{
    void DoSomething(int value, T foo);
}

Now, if we weren’t doing IoC, and we needed a specific FooService for some type T, we’d have to know which type to get.  But you might start to see situations where you need an IFooService, but you don’t really care about the T specifically:

public class SomethingThatUsesFoo<T>
{
    private readonly IFooService<T> _service;

    public SomethingThatUsesFoo(IFooService<T> service)
    {
        _service = service;
    }

    public void SomethingSpecific(T value)
    {
        _service.DoSomething(4, value);
    }
}

As you start to build more and more generic components, building out common infrastructure components, you’ll start to build more common services like these, that coordinate between a messages and their handlers.  In most cases like these, we’re not using generics for type safety, but rather for metadata to match up input types to output services.  A more concrete example on a real project looks like this:

public interface IHandler<TEvent> 
{
    void Handle(TEvent args);
}

This is an interface for domain events, where we’ll have handlers like:

public class OrderCanceledEvent
    : IHandler<OrderCanceledMessage>
{
    public void Handle(OrderCanceledMessage args)
    {
        // send an email or something
    }
}

Now the trick is, how do we instruct our Inversion of Control container to locate the right handler for the right event?  If you’re using StructureMap, it’s dirt, dirt simple.

Configuring StructureMap

Because we’re using StructureMap, we’ll be using a custom Registry to do our configuration.  To connect implementations, we want to make sure that any time we ask StructureMap for an IHandler, it finds the concrete type of handler T.  In the above example, our common message routing code will ask for an IHandler, and the type located needs to be OrderCanceledEvent, because OrderCanceledEvent implements the IHandler.

Our Registry winds up being very simple:

public class HandlerRegistry : Registry
{
    public HandlerRegistry()
    {
        Scan(cfg =>
        {
            cfg.TheCallingAssembly();
            cfg.IncludeNamespaceContainingType<OrderCanceledEvent>();
            cfg.ConnectImplementationsToTypesClosing(typeof(IHandler<>));
        });
    }
}

To connect implementations to our open generic type of IHandler, we use the ConnectImplementationsToTypesClosing method.  The other two are just directions telling StructureMap where to look for my handlers.  Typically, my registration code lives in the same assembly as the actual interfaces I’m registering, but you can also register by name.

But that’s it!  Very simple, one line to connect all of the handlers to their implementations.  I can verify this with a simple test:

[Test]
public void Should_connect_types()
{
    ObjectFactory.Initialize(init =>
    {
        init.AddRegistry<HandlerRegistry>();
    });

    ObjectFactory.AssertConfigurationIsValid();

    Debug.WriteLine(ObjectFactory.WhatDoIHave());

    var handler = ObjectFactory.GetInstance<IHandler<OrderCanceledMessage>>();

    handler.ShouldBeInstanceOf<OrderCanceledEvent>();
}

This test passes, and all is well in IoC land.

Embracing the container

At some point, users of IoC learn to stop caring and love the bomb container.  In our system, we have no less than ten usages of this method, meaning we have refactored a lot of common plumbing and coordinators into our infrastructure layer.  We can easily add new handlers, mappers, repositories, providers, commands, builders, invokers, etc., all with one line of configuration for each open type (NOT one per derived type/implementation).  It certainly opens the doors to new possibilities of separation of concerns between different pieces, we just happen to lean on the type system to route our information around.

Something to note here is that at no time did I need to describe the implementors.  StructureMap’s scanner merely found implementations of types closing IHandler, and connected that concrete type to the requested type of IHandler.  I’ve taken a look at the other containers, and frankly, I haven’t found any that match this level of simplicity in configuration.  But I’m not an expert on the other containers, so I’d love to be proven wrong!

Regardless, I absolutely love this pattern of usage in IoC.  It promotes a level of SOLID design that’s pretty tough to beat.  When folks talk about IoC only being useful in large or complex projects, I just don’t understand it.  Usages like this give me Separation of Concerns from the get-go, at almost zero cost.  If only other frameworks were built with this in mind

Enabling IoC in ASP.NET ActionResults (or, a better ActionResult)