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

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

В частности, почему 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 

2 ответа

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


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


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).

Другие вопросы по тегам