我使用Unity的注册按照惯例机制在以下情形:为什么在指定生命期管理器时注册了两次类型?
public interface IInterface { }
public class Implementation : IInterface { }
鉴于Implementation
类和它的接口,我以下列方式运行RegisterTypes
:
unityContainer.RegisterTypes(
new[] { typeof(Implementation) },
WithMappings.FromAllInterfaces,
WithName.Default,
WithLifetime.ContainerControlled);
在此之后电话,unitContainer
包含三个注册:
IUnityContainer
- >IUnityContainer
(OK)IInterface
- >Implementation
(OK)Implementation
- >Implementation
(???)
当我改变呼叫如下:
unityContainer.RegisterTypes(
new[] { typeof(Implementation) },
WithMappings.FromAllInterfaces,
WithName.Default);
该容器只包含两个注册:
IUnityContainer
- >IUnityContainer
(OK)IInterface
- >Implementation
(OK)
(这是所希望的行为)。
偷看Unity's source code后,我注意到对IUnityContainer.RegisterType
应该如何工作有一些误解。
的RegisterTypes
方法的工作如下(注释表明什么是在上面提出的方案中的值):
foreach (var type in types)
{
var fromTypes = getFromTypes(type); // { IInterface }
var name = getName(type); // null
var lifetimeManager = getLifetimeManager(type); // null or ContainerControlled
var injectionMembers = getInjectionMembers(type).ToArray(); // null
RegisterTypeMappings(container, overwriteExistingMappings, type, name, fromTypes, mappings);
if (lifetimeManager != null || injectionMembers.Length > 0)
{
container.RegisterType(type, name, lifetimeManager, injectionMembers); // !
}
}
因为fromTypes
不为空,则RegisterTypeMappings
添加一种类型的映射:IInterface
- >Implementation
(正确)。
然后,当lifetimeManager
不为空的情况下,代码试图改变一生Manager与以下电话:
container.RegisterType(type, name, lifetimeManager, injectionMembers);
这个函数的名字完全是误导,因为the documentation明确指出:
RegisterType使用容器给定类型和名称的LifetimeManager。这种类型没有执行类型映射。
不幸的是,不仅名称具有误导性,而且文档也是错误的。调试此代码时,我注意到,当没有从type
(Implementation
在上面提供的场景中)的映射时,它被添加(作为type
- >type
),这就是为什么我们最终在第一个场景中有三个注册。
我已经下载了统一的来源,以解决这个问题,但我发现下面的单元测试:
[TestMethod]
public void RegistersMappingAndImplementationTypeWithLifetimeAndMixedInjectionMembers()
{
var container = new UnityContainer();
container.RegisterTypes(new[] { typeof(MockLogger) }, getName: t => "name", getFromTypes: t => t.GetTypeInfo().ImplementedInterfaces, getLifetimeManager: t => new ContainerControlledLifetimeManager());
var registrations = container.Registrations.Where(r => r.MappedToType == typeof(MockLogger)).ToArray();
Assert.AreEqual(2, registrations.Length);
// ...
- 这几乎恰好我的情况,并导致我的问题:
为什么这是预期的?这是一个概念错误,是为了匹配现有的行为而创建的单元测试,但不一定是正确的,还是我错过了重要的东西?
我正在使用Unity v4.0.30319。
当存在多个接口时,被迫拥有默认生命期管理器的多个实例的部分似乎是一个有力的论据,也是目前唯一的具体原因。谢谢! – BartoszKP