Структурная карта, странное поведение при использовании экземпляра по умолчанию и параметров именованного экземпляра

Кто-нибудь может объяснить следующее поведение?

Особенно, почему TestInitializeAndConfigure_Fails терпит неудачу, когда TestUseAndAdd не... и почему 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 

person Stig    schedule 21.09.2011    source источник


Ответы (2)


Просто чтобы помочь людям, которые наткнутся на это, вот ответ от самого человека Джерми. Он ответил на вопрос в своем блоге здесь .


For().Use() является деструктивным. Сделайте For().Use() один раз, чтобы получить значение по умолчанию, и второй вызов For().Add(), чтобы получить вторую регистрацию. Посмотрите комментарии Xml для этих двух вызовов API.


person Sai Gudigundla    schedule 22.01.2012
comment
Это только отвечает на часть его первоначального вопроса. Для меня реальная проблема заключается в том, что тест инициализируется и настраивается с ошибкой (и где у меня также есть проблема). Я думаю, это ошибка. - person Warren Parks; 06.03.2014

TestUse_Fails имеет смысл для меня, потому что вызов Use‹>() по сути означает, что вы указываете экземпляр по умолчанию для типа (и добавляете его). Обычно побеждает последний — я не могу найти подробные документы по этому поводу, но так работает большинство контейнеров. Вызов r1 получает TheSecondResource (последний установлен по умолчанию), а вызов r2 получает именованный ресурс.

TestUseOrderChanged работает, потому что по умолчанию после init/config используется TheFirstResource, но TheSecondResource все еще был добавлен в контейнер с именем. Таким образом, r1 получает TheFirstResource (поскольку он был последним и, следовательно, по умолчанию), а r2 правильно получает TheSecondResource как именованный экземпляр.

TestInitializeAndConfigure_Fails — странный. С того места, где я сижу, r1 должен получить TheFirstResource, поскольку значение по умолчанию не было перезаписано — Use‹>() больше не вызывался. Вызов Configure после вызова Initialize не должен сбрасывать контейнер в соответствии с документацией. Я бы попробовал вызвать ObjectFactory.WhatDoIHave() и посмотреть, зарегистрирован ли TheFirstResource после вызовов Initialize() и Configure().

Для меня это выглядит как ошибка, и я бы подумал о том, чтобы отправить ее в группу пользователей Structuremap (http://groups.google.com/group/structuremap-users).

person Phil Sandler    schedule 21.09.2011