在手动注册UnityServiceLocator时,Unity不尊重HierarchicalLifetimeManager

时间:2013-03-15 11:36:34

标签: c# unity-container

在使用IServiceLocator注册和解析HierarchicalLifetimeManager时,我在Unity中看到了一些意外行为。

我所看到的是,当您注册时,Unity会将具体类型UnityServiceLocator视为特殊情况。它将类型视为静态单例,即使它不应该。这种行为似乎特别适用于UnityServiceLocator

背景:我正在我们的代码中的一些地方慢慢淘汰“静态”ServiceLocator。第一步是在Unity中注册IServiceLocator,然后将其作为依赖注入到使用它的类中。

在以下代码中,我注册了一个注入工厂来创建UnityServiceLocator的新实例。我还使用HierarchicalLifetimeManager来限定它,以便为每个子容器提供一个实例:

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
}

我希望上面的代码调用工厂,创建UnityServiceLocator实例并写出控制台输出三次,每个容器一次。 它没有 - 它只做了一次,好像我把它注册为单身:

  

使用容器调用的InjectionFactory:20903718

情况变得更糟:

如果我现在创建自己的类实现IServiceLocator(字面意思是实现接口,一个ctor接受IUnityContainer,并且所有方法都抛出NotImplementedException),并交换行< / p>

     return new UnityServiceLocator(c);

     return new MyUnityServiceLocator(c);

这开始按照我期望的方式行事:

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

除非Unity将UnityServiceLocator视为特例,否则我无法理解这种行为。 有没有人对此行为有任何其他解释?我是否遗漏了一些明显的东西,或者Unity内部将UnityServiceLocator视为特殊情况并忽略了我指定的生命周期策略?

1 个答案:

答案 0 :(得分:1)

事实证明,UnityServiceLocator是一种特殊情况 - 它首次创建时,在其自己的构造函数中使用ExternallyControlledLifetimeManager注册本身

有关更多信息,请参阅Randy Levy的评论:unity.codeplex.com/workitem/12727