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

时间:2011-09-21 14:07:13

标签: c# structuremap instances named

有人能够解释以下行为吗?

特别是为什么当TestUseAndAdd没有时,TestInitializeAndConfigure_Fails会失败...以及当TestUseOrderChanged没有时,为什么TestUse_Fails会失败。

谢谢

代码

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 

2 个答案:

答案 0 :(得分:2)

只是为了帮助那些偶然发现这一点的人,这是Jermey自己的回答。他在他的博客here上回答了这个问题。


For()。Use()具有破坏性。 Do For()。使用()一次获得默认值,第二次调用For()。Add()获得第二次注册。查看这两个API调用的Xml注释。


答案 1 :(得分:1)

TestUse_Fails对我来说很有意义,因为调用Use&lt;&gt;()实质上意味着您要为该类型指定默认实例(并添加它)。最后一个通常会赢 - 我找不到明确的文档,但这是大多数容器的工作方式。 r1调用获取TheSecondResource(最后一个设置为默认值),r2调用获取命名资源。

TestUseOrderChanged有效,因为init / config之后的默认值是TheFirstResource,但是TheSecondResource仍然被添加到带有名称的容器中。因此r1获取TheFirstResource(因为它是最后一个,因此是默认值),并且r2正确地将TheSecondResource作为命名实例。

TestInitializeAndConfigure_Fails是奇怪的。从我所在的位置开始,r1应该获得TheFirstResource,因为默认值没有被覆盖 - 使用&lt;&gt;()没有被再次调用。调用Initialize后调用Configure应该根据文档重置容器。我会尝试调用ObjectFactory.WhatDoIHave()并查看在Initialize()和Configure()调用之后是否甚至注册了TheFirstResource。

对我而言,这看起来像一个错误,我会考虑将其提交给结构图用户组(http://groups.google.com/group/structuremap-users)。