1

Вот упрощенная версия пары классов в моем решении и интерфейсах, которые они реализуют. Они совместно используют один интерфейс, а также реализуют выделенный интерфейс.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, соответствуют именам параметров в конструкторе.

Update

Вот обновленный раздел реестра, который необходим, чтобы сделать мой пример случая работы. Благодаря @ Jeremy-d-мельник за информацию мне нужно было:

this.For<IMyDependent>().Use<MyDependent>() 
    .Ctor<ISharedContract>("cOne").Is<ConcreteOne>() 
    .Ctor<ISharedContract>("cTwo").Is<ConcreteTwo>(); 

ответ

2

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.

+0

Благодарим за обновление, особенно ссылку. Несомненно, это правильный ответ. Но я не понимаю, как код, который я написал, работал для меня в прошлом. Я дважды проверял, и я вижу, что он работает в существующем коде. Любая идея, как это могло быть? – getsetcode