Unity容器 - 在同一个类上映射两个接口时应用了错误的注册

时间:2017-06-23 08:18:33

标签: c# dependency-injection unity-container

我有一个实现两个接口的类:

interface IA { int X { get; } }
interface IB { int X { get; } }

class C : IA, IB
{
    public C(int x) { X = x; }
    public int X { get; }
}

然后我将IAIB映射到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.因此使用第二次注册而不是第一次注册。

谁可以解释,为什么以上注册互相干扰?这有什么明智的理由吗?

1 个答案:

答案 0 :(得分:1)

从(简化的)高级别Unity存储解析时使用的两条信息:

  1. 类型映射
  2. 构建计划
  3. 要记住的关键点是类型映射和目标类型的构建是单独的离散步骤。

    类型映射存储“from”类型和“to”类型之间的映射。因此,在示例代码中IA =&gt; CIB =&gt; C

    构建计划包含构建“到”目标类型所需的步骤。在这种情况下,该类型为C

    所以当

    .RegisterType<IA, C>(new InjectionConstructor(1))
    

    被称为从IAC创建的类型映射,并且创建与目标类型C相关联的构建计划策略并将其保存在内存中。构建计划策略将包括默认生命周期管理器和值为1的InjectionConstructor

    下一次

    .RegisterType<IB, C>(new InjectionConstructor(2));
    

    被称为从IBC创建的类型映射,并且在内存中更新与目标类型C相关联的构建计划策略。这会更改构建计划策略以使用InjectionConstructor(2)而不是InjectionConstructor(1)

    现在定义了两个类型映射(IA = CIB =&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