Verifying the object graph for dependency injection

I've been an avid reader of Steven van Deursen's blog, and I especially found his take on a command/query separation to be a very reasonable, SOLID approach. I've implemented queries for one of my applications using the IQuery<>, IQueryHandler<,> and IQueryProcessor interfaces from the mentioned blog post.

When using dependency injection for the IQueryHandler<,>, it quickly leads to some pretty messy constructors when injecting multiple handlers. One way to alleviate this is to employ the IQueryProcessor, which dynamically locates the appropriate query handlers in the IoC container. However, the drawback is that this makes it harder for my DI framework to verify the object graph, because there's no longer any direct injection of IQueryHandler<,> when the object graph is created.

Here's an example without using IQueryProcessor:

public class ActivityController : Controller
{
    private readonly IQueryHandler<GetLatestActivityQuery, Activity>
        _getLatestActivityQueryHandler;

    private readonly IQueryHandler<GetAllActivitiesForUserQuery, IEnumerable<Activity>>
        _getAllActivitiesForUserQueryHandler;

    private readonly IQueryHandler<GetActivitiesWithinTimeframeQuery, IEnumerable<Activity>>
        _getActivitiesWithinTimeframeQueryHandler;

    // Here, the DI framework can verify that the query handlers exists in the constructor
    public ActivityController(
        IQueryHandler<GetLatestActivityQuery, Activity> getLatestActivityQueryHandler,
        IQueryHandler<GetAllActivitiesForUserQuery, IEnumerable<Activity>> getAllActivitiesForUserQueryHandler,
        IQueryHandler<GetActivitiesWithinTimeframeQuery, IEnumerable<Activity>> getActivitiesWithinTimeframeQueryHandler);
    {
        _getLatestActivityQueryHandler = getLatestActivityQueryHandler;
        _getAllActivitiesForUserQueryHandler = getAllActivitiesForUserQueryHandler;
        _getActivitiesWithinTimeframeQueryHandler = _getActivitiesWithinTimeframeQueryHandler;
    }

    public ActionResult GetLatestActivity()
    {
        var latestActivity = _getLatestActivityQueryHandler.Handle(new GetLatestActivityQuery());
        return View(latestActivity);
    }

   ...

With IQueryProcessor, the same functionality can be achieved with this:

public class ActivityController : Controller
{
    private readonly IQueryProcessor _queryProcessor;

    // The DI framework can only verify that the IQueryProcessor exists here
    public ActivityController(IQueryProcessor queryProcessor);
    {
        _queryProcessor = queryProcessor;
    }

    public ActionResult GetLatestActivity()
    {
        // This is where the appropriate IQueryHandler<,> is first instantiated, so if
        // the IoC container can't locate an appropriate handler, it'll throw an exception
        var latestActivity = _queryProcessor.Process(new GetLatestActivityQuery());
        return View(latestActivity);
    }

   ...

The code is much cleaner and more readable, and the intent is still clear, but I still haven't verified that the required handler can actually be resolved. Fortunately, I can verify that all of the required IQuery<>/IQueryHandler<,> pairs exist, by using a test with reflection. I don't have much experience with reflection, so this can likely be optimized - but a simple, working solution is as follows:

  1. Get all query types in the system.
  2. Build a list of matching query handlers.
  3. Verify that the required query handlers are implemented.
var queryType = typeof (IQuery<>);
var queryHandlerType = typeof (IQueryHandler<,>);

var types = Assembly.GetAssembly(queryType).ExportedTypes;
var queries = types.Where(t => t.GetInterface(queryType.Name) != null);

var matchingQueryHandlers = queries
    .Select(query => queryHandlerType.MakeGenericType(
        query, query.GetInterface(queryType.Name).GenericTypeArguments[0]));

// xunit.net
Assert.All(matchingQueryHandlers, handler => types.Any(t => t.IsAssignableFrom(handler)));

In addition to this, I've added a few more constraints - mostly for my own sanity - which are validated with separate tests:

  • Only one IQuery<> per concrete implementation.
  • Only one query handler per concrete IQuery<> implementation.

These tests allow me to rest assured that my object graph can be properly constructed by my DI framework.

Introducing Sparum

I've been toying around with different ideas and concepts for web applications for a while now. Partly because it's always satisfying to learn new things and apply them in practice, but also because it's simply fun and interesting. I work with web applications daily, and I enjoy solving the challenges they raise. While researching solutions to a particular problem, I often stumble upon solutions to problems I don't have yet. And that's frustrating at times, because those solutions can be pretty cool!

So, my solution to that problem is to start a little web application project of my own. I've named it Sparum, and the intent is to use it as a sandbox project for programming patterns, and throwing in some pretty cool libraries and new technologies along the way. It's a .NET/C#-based forum platform with a single-page application (SPA) frontend: thereby the name Sparum. Source code on GitHub as always.

My overall aims are:

  • Separation of UI and platform
  • Separation of data and behavior
  • Infrastructure as an implementation detail
  • Meaningful unit and integration tests
  • Thorough, up-to-date documentation
  • Build and test automation

While most of these are obvious for any application with an ambition for quality, it's still important to write them down so that I can hold myself to them. I'll be rigorous about these, as they'll make my life easier when maintaining and adding new features to the application as I progress. Rome wasn't built in a day, and Sparum won't be either!

I do plan to focus more on code and technical details in future posts about Sparum, but I thought I'd give it a short introduction first for some reference.