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 

Structuremap,使用默认实例和命名实例选项时的奇怪行为

为了帮助那些偶然发现这个问题的人,下面是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)。