Structuremap,使用默认实例和命名实例选项时的奇怪行为
本文关键字:实例 选项 默认 Structuremap | 更新日期: 2023-09-27 18:09:09
有人能解释一下下面的行为吗?
特别是为什么TestUseAndAdd没有TestInitializeAndConfigure_Fails失败…为什么TestUse_Fails失败,而TestUseOrderChanged没有。
感谢interface IResource {}
class TheFirstResource : IResource {}
class TheSecondResource : IResource {}
[TestFixture]
class Test
{
[Test]
public void TestUse_Fails()
{
ObjectFactory.Initialize(init =>
{
init.For<IResource>().Singleton().Use<TheFirstResource>();
init.For<IResource>().Singleton().Use<TheSecondResource>().Named("test");
});
IResource r1 = ObjectFactory.GetInstance<IResource>();
IResource r2 = ObjectFactory.GetNamedInstance<IResource>("test");
Console.WriteLine(string.Format("TestUse_Fails 'n{0}'n{1}", r1, r2));
}
[Test]
public void TestUseOrderChanged()
{
ObjectFactory.Initialize(init =>
{
init.For<IResource>().Singleton().Use<TheSecondResource>().Named("test");
init.For<IResource>().Singleton().Use<TheFirstResource>();
});
IResource r1 = ObjectFactory.GetInstance<IResource>();
IResource r2 = ObjectFactory.GetNamedInstance<IResource>("test");
Console.WriteLine(string.Format("TestUseOrderChanged 'n{0}'n{1}", r1, r2));
}
[Test]
public void TestUseAndAdd()
{
ObjectFactory.Initialize(init =>
{
init.For<IResource>().Singleton().Use<TheFirstResource>();
init.For<IResource>().Singleton().Add<TheSecondResource>().Named("test");
});
IResource r1 = ObjectFactory.GetInstance<IResource>();
IResource r2 = ObjectFactory.GetNamedInstance<IResource>("test");
Console.WriteLine(string.Format("TestUseAndAdd 'n{0}'n{1}", r1, r2));
}
[Test]
public void TestInitializeAndConfigure_Fails()
{
ObjectFactory.Initialize(init =>
{
init.For<IResource>().Singleton().Use<TheFirstResource>();
});
ObjectFactory.Configure(init =>
{
init.For<IResource>().Singleton().Add<TheSecondResource>().Named("test");
});
IResource r1 = ObjectFactory.GetInstance<IResource>();
IResource r2 = ObjectFactory.GetNamedInstance<IResource>("test");
Console.WriteLine(string.Format("TestInitializeAndConfigure_Fails 'n{0}'n{1}", r1, r2));
}
}
TestUse_Fails
Smtesting.TheSecondResource
Smtesting.TheSecondResource
TestUseOrderChanged
Smtesting.TheFirstResource
Smtesting.TheSecondResource
TestInitializeAndConfigure_Fails
Smtesting.TheSecondResource
Smtesting.TheSecondResource
TestUseAndAdd
Smtesting.TheFirstResource
Smtesting.TheSecondResource
为了帮助那些偶然发现这个问题的人,下面是jeremy自己的回答。他在自己的博客上回答了这个问题。
For(). use()是破坏性的。执行For(). use()一次以获得默认值,并再次调用For(). add()以获得第二次注册。查看这两个API调用的Xml注释
TestUse_Fails对我来说是有意义的,因为调用Use<>()本质上意味着您正在为类型指定默认实例(并添加它)。最后一个通常会胜出——我找不到关于这方面的明确文档,但这是大多数容器的工作方式。r1调用获得TheSecondResource(最后一个设置为默认值),r2调用获得命名资源。
TestUseOrderChanged工作,因为init/config后的默认值是TheFirstResource,但TheSecondResource仍然被添加到一个名称的容器。因此,r1获得TheFirstResource(因为它是最后一个,因此是默认的),而r2正确地获得TheSecondResource作为命名实例。
TestInitializeAndConfigure_Fails是奇数。从我的位置来看,r1应该得到TheFirstResource,因为默认值没有被覆盖——Use<>()没有被再次调用。在调用Initialize之后调用Configure应该而不是根据文档重置容器。我会尝试调用ObjectFactory.WhatDoIHave(),看看是否TheFirstResource甚至在Initialize()和Configure()调用后注册。
对我来说,这看起来像是一个bug,我会考虑将它提交给structuremap用户组(http://groups.google.com/group/structuremap-users)。