Cook Computing

Logging of Unity Resolution Failure

March 6, 2009 Written by Charles Cook

When using the Unity Dependency Injection container I've found that when a resolution of a dependency fails the Message property of the resulting ResolutionFailed exception is not immediately useful if there is more than one level of dependencies being resolved. For example this code:


using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;

interface ILogger
{
}

class Foo
{
  public Foo(ILogger logger)
  {
  }
}

class Bar
{
  public Bar(Foo foo)
  {
  }
}

class Program
{
  static void Main(string[] args)
  {
    var unity = new UnityContainer();
    unity.Resolve(typeof(Bar));
  }
}

Results in the following exception message:

Resolution of the dependency failed, type = "Bar", name = "". Exception message is: The current build operation (build key Build Key[Bar, null]) failed: The parameter foo could not be resolved when attempting to call constructor Bar(Foo foo). (Strategy type BuildPlanStrategy, index 3)

The information describing why the resolution failed is hidden in the hierachy of inner exceptions. To make this easy to read I use code like the LogResolutionFailed method (just writing to the console in this example):


class Program
{
  static void Main(string[] args)
  {
    try
    {
      var unity = new UnityContainer();
      unity.Resolve(typeof(Bar));
    }
    catch (ResolutionFailedException rfex)
    {
      LogResolutionFailed(rfex);
    }
  }

  static void LogResolutionFailed(ResolutionFailedException rfex)
  {
    Console.WriteLine("ResolutionFailedException for {0} {1}", 
      rfex.TypeRequested, rfex.NameRequested);
    var messages = new Stack<string>();
    var inner = rfex.InnerException;
    while (inner != null)
    {
      if (inner is InvalidOperationException)
        Console.WriteLine(inner.Message);
      inner = inner.InnerException;
    }
  }
}

Results in the following output which makes the cause of the resolution failure more obvious:

ResolutionFailedException for Bar

The parameter foo could not be resolved when attempting to call constructor Bar(Foo foo).

The parameter logger could not be resolved when attempting to call constructor Foo(ILogger logger).

The current type, ILogger, is an interface and cannot be constructed. Are you missing a type mapping?

I'm currently working on a debugger visualizer for ResolutionFailedException so that the same information can be seen in the debugger, instead of having to drill down into the inner exceptions.