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,

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