StructureMap 4 с именованными экземплярами не работает должным образом
Вот упрощенная версия пары классов в моем решении и интерфейсы, которые они реализуют. Они оба используют один интерфейс, а также реализуют выделенный интерфейс.
public interface ISharedContract
{
void ImplementSharedContract();
}
public interface IConcreteOne
{
void ImplementConcreteOne();
}
public interface IConcreteTwo
{
void ImplementConcreteTwo();
}
public class ConcreteOne : BaseConcrete, IConcreteOne, ISharedContract
{
public void ImplementSharedContract()
{
this.ImplementConcreteOne();
}
public void ImplementConcreteOne()
{
}
}
public class ConcreteTwo : BaseConcrete, IConcreteTwo, ISharedContract
{
public void ImplementSharedContract()
{
this.ImplementConcreteTwo();
}
public void ImplementConcreteTwo()
{
}
}
Мой реестр StructureMap регистрирует эти зависимости следующим образом:
public class MyRegistry : Registry
{
public MyRegistry()
{
this.For<ISharedContract>().Use<ConcreteOne>().Named("cOne");
this.For<ISharedContract>().Use<ConcreteTwo>().Named("cTwo");
this.For<IConcreteOne>().Use<ConcreteOne>();
this.For<IConcreteTwo>().Use<ConcreteTwo>();
}
}
Наконец, у меня есть класс, который внедряет эти зависимости в конструктор следующим образом:
public MyDependent(ISomethingElse somethingElse, ISharedContract cOne, ISharedContract cTwo)
{
this.collection = new List<ISharedContract>()
{
cOne,
cTwo
};
}
Во время выполнения я наблюдаю, что cOne и cTwo - оба введенные экземпляры ConcreteTwo
, Если я поменяю местами порядок двух именованных регистраций в реестре StructureMap, то cOne и cTwo будут экземплярами ConcreteOne
,
Я не первый раз использую именованные экземпляры, но раньше такого не наблюдал. Я что-то упускаю? Я проверил и дважды проверил, что значения, передаваемые в метод Named, соответствуют именам параметров в конструкторе.
Обновить
Вот обновленная запись в реестре, которая необходима для работы моего примера. Спасибо @jeremy-d-miller за необходимую информацию:
this.For<IMyDependent>().Use<MyDependent>()
.Ctor<ISharedContract>("cOne").Is<ConcreteOne>()
.Ctor<ISharedContract>("cTwo").Is<ConcreteTwo>();
1 ответ
StructureMap не имеет никакой магической функциональности, которая сопоставляет имена параметров вашего конструктора с именованным экземпляром этого типа. В этом случае вам придется явно отобразить встроенные зависимости: http://structuremap.github.io/registration/inline-dependencies/
В этом коде:
this.For<ISharedContract>().Use<ConcreteOne>().Named("cOne");
this.For<ISharedContract>().Use<ConcreteTwo>().Named("cTwo");
Вы устанавливаете по умолчанию ISharedContext
в ConcreteOne
затем немедленно переопределить это ConcreteTwo
, Последний выигрывает в этом случае. Когда вы строите свой MyDependent
Класс StructureMap просто использует автоматическое подключение, чтобы выдвинуть экземпляр по умолчанию ISharedContext
,