开发者

Structuremap, odd behavior when using default instance and named instance Options

开发者 https://www.devze.com 2023-04-06 05:27 出处:网络
Is anybody able to explain the following behavior? Especially why TestInitializeAndConfigure_Fails failes when TestUseAndAdd does not ... and why TestUse_Fails failes when TestUseOrderChanged does n

Is anybody able to explain the following behavior?

Especially why TestInitializeAndConfigure_Fails failes when TestUseAndAdd does not ... and why TestUse_Fails failes when TestUseOrderChanged does not.

Thanks

code

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.Writ开发者_开发百科eLine(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));
    }
}

output

TestUse_Fails 
Smtesting.TheSecondResource 
Smtesting.TheSecondResource 

TestUseOrderChanged 
Smtesting.TheFirstResource 
Smtesting.TheSecondResource 

TestInitializeAndConfigure_Fails 
Smtesting.TheSecondResource 
Smtesting.TheSecondResource 

TestUseAndAdd 
Smtesting.TheFirstResource 
Smtesting.TheSecondResource 


Just to help the people who will stumble upon this, here is an answer from the man Jermey himself. He answered the question on his blog here.


For().Use() is destructive. Do For().Use() once to get the default, and a second call to For().Add() to get the 2nd registration. Look at the Xml comments for those 2 API calls.



TestUse_Fails makes sense to me, because calling Use<>() essentially means you are specifying the default instance for the type (and adding it). Last one in generally wins--I can't find explicit docs on this, but that's the way most containers work. The r1 call gets TheSecondResource (the last one set to be default), and the r2 call gets the named resource.

TestUseOrderChanged works because the default after init/config is the TheFirstResource, but TheSecondResource has still been added to the container with a name. So r1 gets TheFirstResource (as it was last in and thus the default), and r2 correctly gets TheSecondResource as the named instance.

TestInitializeAndConfigure_Fails is the odd one. From where I sit, r1 should get TheFirstResource, since the default has not been overwritten--Use<>() has not been called again. Calling Configure after calling Initialize should not reset the container according to the docs. I would try calling ObjectFactory.WhatDoIHave() and see if TheFirstResource is even registered after the Initialize() and Configure() calls.

To me, this looks like a bug, and I would consider submitting it to the structuremap users group (http://groups.google.com/group/structuremap-users).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号