具有相同类型的命名和未命名注册的意外 Unity 容器行为
Unexpected Unity container behaviour with named and unnamed registration for same type
我使用的是 Unity 版本 2.1.505.2,在使用默认注册和命名注册(使用 ParameterOverride
)为相同接口类型注册 UnityContainer
时看到意外行为。
如果我调用 container.Resolve<T>()
两次 - 一次用于命名注册,一次用于默认注册 - 我会得到相同的实例,而我期望基于两个不同注册的不同实例。
这是一个代码示例:
public interface ICage
{
IAnimal Animal { get; }
}
public class Cage : ICage
{
public IAnimal Animal { get; private set; }
public Cage(IAnimal animal) { Animal = animal; }
}
public interface IAnimal
{
string Species { get; }
}
public class Cat : IAnimal
{
public string Species { get { return "Felis catus"; } }
}
public class Dog : IAnimal
{
public string Species { get { return "Canis lupus"; } }
}
[TestClass]
public class UnityTest
{
[TestMethod]
public void MyTest()
{
var container = new UnityContainer();
// Default registrations for IAnimal and ICage
container.RegisterType<IAnimal, Cat>(new ContainerControlledLifetimeManager());
container.RegisterType<ICage, Cage>(new ContainerControlledLifetimeManager());
// Named registration "cage2" for ICage mapping to Cage with constructor parameter override
container.RegisterType<ICage>(
"cage2",
new ContainerControlledLifetimeManager(),
new InjectionFactory(c => c.Resolve<Cage>(new ParameterOverride("animal", new Dog()))));
// Resolve ICage using the named registraion "cage2"
var cage2 = container.Resolve<ICage>("cage2");
Assert.AreEqual("Canis lupus", cage2.Animal.Species); // Assert succeeds
// Resolve ICage using the default registration ???
var cage = container.Resolve<ICage>();
Assert.AreEqual("Felis catus", cage.Animal.Species); // Assert fails (Actual:<Canis lupus>)
}
}
测试中的第二个断言失败,因为cage.Animal.Species
returns "Canis lupus"
.
我在这里的理解是否遗漏了什么?我该如何设置,以便调用 container.Resolve<ICage>("cage2")
returns 对应两个命名注册的 Cage
实例,以及调用 container.Resolve<ICage>()
returns 实例对应默认注册?
我花了 2 天时间解决了你的问题,我解决了!
问题出在命名注册中 "cage2"。
当你打电话时:
var cage2 = container.Resolve<ICage>("cage2");
你运行:
new InjectionFactory(c => c.Resolve<Cage>(new ParameterOverride("animal", new Dog()))));
看内部c.Resolve<Cage>
,当它调用unity创建的对象Cage
和new Dog()
作为IAnimal时。但!以上,您注册的类型:
container.RegisterType<ICage, Cage>(new ContainerControlledLifetimeManager());
所以!内部 c.Resolve<Cage>
使用 Dog
为对象 Cage
创建无命名注册。而且,当它注册为 ContainerControlled 时,它保存值,当您调用时:
var cage = container.Resolve<ICage>();
你得到的价值,已经被创造出来了!
固定解:
[TestClass]
public class UnityTest
{
[TestMethod]
public void MyTest()
{
var container = new UnityContainer();
// Default registrations for IAnimal and ICage
container.RegisterType<IAnimal, Cat>(new ContainerControlledLifetimeManager());
container.RegisterType<ICage, Cage>(new ContainerControlledLifetimeManager());
container.RegisterType<ICage>(
"cage2",
new ContainerControlledLifetimeManager(),
new InjectionFactory(c => new Cage(new Dog())));
// Resolve ICage using the named registraion "cage2"
var cage2 = container.Resolve<ICage>("cage2");
Assert.AreEqual("Canis lupus", cage2.Animal.Species); // Assert succeeds
// Resolve default
var cage = container.Resolve<ICage>();
Assert.AreEqual("Felis catus", cage.Animal.Species); // Assert succeeds
}
}
我使用的是 Unity 版本 2.1.505.2,在使用默认注册和命名注册(使用 ParameterOverride
)为相同接口类型注册 UnityContainer
时看到意外行为。
如果我调用 container.Resolve<T>()
两次 - 一次用于命名注册,一次用于默认注册 - 我会得到相同的实例,而我期望基于两个不同注册的不同实例。
这是一个代码示例:
public interface ICage
{
IAnimal Animal { get; }
}
public class Cage : ICage
{
public IAnimal Animal { get; private set; }
public Cage(IAnimal animal) { Animal = animal; }
}
public interface IAnimal
{
string Species { get; }
}
public class Cat : IAnimal
{
public string Species { get { return "Felis catus"; } }
}
public class Dog : IAnimal
{
public string Species { get { return "Canis lupus"; } }
}
[TestClass]
public class UnityTest
{
[TestMethod]
public void MyTest()
{
var container = new UnityContainer();
// Default registrations for IAnimal and ICage
container.RegisterType<IAnimal, Cat>(new ContainerControlledLifetimeManager());
container.RegisterType<ICage, Cage>(new ContainerControlledLifetimeManager());
// Named registration "cage2" for ICage mapping to Cage with constructor parameter override
container.RegisterType<ICage>(
"cage2",
new ContainerControlledLifetimeManager(),
new InjectionFactory(c => c.Resolve<Cage>(new ParameterOverride("animal", new Dog()))));
// Resolve ICage using the named registraion "cage2"
var cage2 = container.Resolve<ICage>("cage2");
Assert.AreEqual("Canis lupus", cage2.Animal.Species); // Assert succeeds
// Resolve ICage using the default registration ???
var cage = container.Resolve<ICage>();
Assert.AreEqual("Felis catus", cage.Animal.Species); // Assert fails (Actual:<Canis lupus>)
}
}
测试中的第二个断言失败,因为cage.Animal.Species
returns "Canis lupus"
.
我在这里的理解是否遗漏了什么?我该如何设置,以便调用 container.Resolve<ICage>("cage2")
returns 对应两个命名注册的 Cage
实例,以及调用 container.Resolve<ICage>()
returns 实例对应默认注册?
我花了 2 天时间解决了你的问题,我解决了!
问题出在命名注册中 "cage2"。
当你打电话时:
var cage2 = container.Resolve<ICage>("cage2");
你运行:
new InjectionFactory(c => c.Resolve<Cage>(new ParameterOverride("animal", new Dog()))));
看内部c.Resolve<Cage>
,当它调用unity创建的对象Cage
和new Dog()
作为IAnimal时。但!以上,您注册的类型:
container.RegisterType<ICage, Cage>(new ContainerControlledLifetimeManager());
所以!内部 c.Resolve<Cage>
使用 Dog
为对象 Cage
创建无命名注册。而且,当它注册为 ContainerControlled 时,它保存值,当您调用时:
var cage = container.Resolve<ICage>();
你得到的价值,已经被创造出来了!
固定解:
[TestClass]
public class UnityTest
{
[TestMethod]
public void MyTest()
{
var container = new UnityContainer();
// Default registrations for IAnimal and ICage
container.RegisterType<IAnimal, Cat>(new ContainerControlledLifetimeManager());
container.RegisterType<ICage, Cage>(new ContainerControlledLifetimeManager());
container.RegisterType<ICage>(
"cage2",
new ContainerControlledLifetimeManager(),
new InjectionFactory(c => new Cage(new Dog())));
// Resolve ICage using the named registraion "cage2"
var cage2 = container.Resolve<ICage>("cage2");
Assert.AreEqual("Canis lupus", cage2.Animal.Species); // Assert succeeds
// Resolve default
var cage = container.Resolve<ICage>();
Assert.AreEqual("Felis catus", cage.Animal.Species); // Assert succeeds
}
}