我有一个实现两个接口的类:
interface IA { int X { get; } }
interface IB { int X { get; } }
class C : IA, IB
{
public C(int x) { X = x; }
public int X { get; }
}
然后我将IA
和IB
映射到Unity容器中的C
,并检查是否使用了正确的注册:
var container = new UnityContainer();
container
.RegisterType<IA, C>(new InjectionConstructor(1))
.RegisterType<IB, C>(new InjectionConstructor(2));
var a = container.Resolve<IA>();
a.X.ShouldBe(1); // Actually it's 2
我在a.X
等于2而不是1.因此使用第二次注册而不是第一次注册。
谁可以解释,为什么以上注册互相干扰?这有什么明智的理由吗?
答案 0 :(得分:1)
从(简化的)高级别Unity存储解析时使用的两条信息:
要记住的关键点是类型映射和目标类型的构建是单独的离散步骤。
类型映射存储“from”类型和“to”类型之间的映射。因此,在示例代码中IA
=&gt; C
和IB
=&gt; C
。
构建计划包含构建“到”目标类型所需的步骤。在这种情况下,该类型为C
。
所以当
.RegisterType<IA, C>(new InjectionConstructor(1))
被称为从IA
到C
创建的类型映射,并且创建与目标类型C
相关联的构建计划策略并将其保存在内存中。构建计划策略将包括默认生命周期管理器和值为1的InjectionConstructor
。
下一次
.RegisterType<IB, C>(new InjectionConstructor(2));
被称为从IB
到C
创建的类型映射,并且在内存中更新与目标类型C
相关联的构建计划策略。这会更改构建计划策略以使用InjectionConstructor(2)
而不是InjectionConstructor(1)
。
现在定义了两个类型映射(IA
= C
和IB
=&gt; C
),但仍然只有C
的一个构建计划。这就是解析返回值2而不是1的原因。(您可以通过直接解析C
并检查X的值来验证这一点:container.Resolve<C>()
)。
如果您想为同一目标类型设置多个构建计划,则可以使用命名注册。例如,您可以使用from接口的名称(或您想要的任何其他字符串值注册,但接口名称似乎适用于此处):
var container = new UnityContainer();
container
.RegisterType<IA, C>(typeof(IA).Name, new InjectionConstructor(1))
.RegisterType<IB, C>(typeof(IB).Name, new InjectionConstructor(2));
var a = container.Resolve<IA>(typeof(IA).Name);
a.X.ShouldBe(1); // will be 1