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.Single(handler.IsAssignableFrom));

This also constrains the number of query handlers to exactly one per query, allowing me to rest assured that my object graph can be properly constructed by my DI framework.

UPDATE 17 Sep 2015: Wrong method listed - assertion should use IEnumerable<T>.Single, not IEnumerable<T>.Any.