在使用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视为特殊情况并忽略了我指定的生命周期策略?
答案 0 :(得分:1)
事实证明,UnityServiceLocator
是一种特殊情况 - 它首次创建时,在其自己的构造函数中使用ExternallyControlledLifetimeManager
注册本身。
有关更多信息,请参阅Randy Levy的评论:unity.codeplex.com/workitem/12727