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



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

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。因此,使用第二个注册而不是第一个注册。

谁能解释,为什么上述注册会相互干扰?有什么理智的理由吗?

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

  1. 类型映射
  2. 建造计划

要记住的关键点是,类型映射和目标类型的构建是单独的离散步骤。

类型映射存储"发件人"类型和"收件人"类型之间的映射。 因此,在示例代码中IA=>CIB=>C

构建计划包含构造"to"目标类型所需的步骤。 在本例中,该类型为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=>C),但仍然只有一个C构建计划。 这就是 resolve 返回值 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

最新更新