Структура карты, странное поведение при использовании экземпляра по умолчанию и именованного экземпляра
Кто-нибудь может объяснить следующее поведение?
В частности, почему 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).