Search code examples
c#unity-container

Unity not respecting HierarchicalLifetimeManager when manually registering UnityServiceLocator


I'm seeing some unexpected behaviour in Unity when registering and resolving IServiceLocator using the HierarchicalLifetimeManager.

What I'm seeing suggests that Unity treats the concrete type UnityServiceLocator as a special case when you register it. It treats the type as a static singleton, even when it shouldn't. This behaviour seems to be particular to UnityServiceLocator.

Background: I am slowly phasing out the "static" ServiceLocator in a few places in our code where it exists. The first step was going to be to register IServiceLocator in Unity and then have it injected as a dependency into those classes that use it.

In the following code, I register an injection factory to create a new instance of UnityServiceLocator. I also scope it with HierarchicalLifetimeManager to give me one instance per child container:

private static void Main(string[] args)
{
    var container = new UnityContainer();
    container.RegisterType<IServiceLocator>(
        new HierarchicalLifetimeManager(),
        new InjectionFactory(
            c =>
                {
                    Console.WriteLine("InjectionFactory invoked with container: " + c.GetHashCode());
                    return new UnityServiceLocator(c);
                }));

    container.Resolve<IServiceLocator>(); // expect to see console output here
    container.Resolve<IServiceLocator>(); // don't expect to see console output here

    var child = container.CreateChildContainer();
    child.Resolve<IServiceLocator>(); // expect to see console output here
    container.Resolve<IServiceLocator>(); // don't expect to see console output here

    var anotherChildContainer = container.CreateChildContainer();
    anotherChildContainer.Resolve<IServiceLocator>(); // expect to see console output here
    anotherChildContainer.Resolve<IServiceLocator>(); // don't expect to see console output here
}

I would expect the above code to invoke the factory, create the UnityServiceLocator instance and write out console output three times, once for each container. It doesn't - it does it once, as if I'd registered it as a singleton:

InjectionFactory invoked with container: 20903718

It gets worse:

If I now make my own class implement IServiceLocator (literally, implement the interface, one ctor which takes IUnityContainer, and have all methods throw NotImplementedException), and swap the line

     return new UnityServiceLocator(c);

with

     return new MyUnityServiceLocator(c);

This starts behaving the way I'd expect:

InjectionFactory invoked with container: 20903718 
InjectionFactory invoked with container: 51746094 
InjectionFactory invoked with container: 41215084

I just cannot understand this behaviour unless Unity treats UnityServiceLocator as a special case. Does anyone have any other explanation for this behaviour? Am I missing something obvious, or is Unity internally treating UnityServiceLocator as a special case and ignoring the lifetime strategy I am specifying?


Solution

  • It turns out that UnityServiceLocator is a special case - it registers itself with ExternallyControlledLifetimeManager in it's own constructor when it is first created.

    See Randy Levy's comment here for more information: unity.codeplex.com/workitem/12727