2017-01-17 33 views
0

Этот вопрос очень похож на вопрос, который я ранее просил (и ответил): Structure Map - Collection of Dependencies in ConstructorСтруктура Карта - Вводить Коллекция именованных экземпляров

В моем реестре у меня есть следующие:

For<IMyObject>().Add<MyObjectType1>().Named("Type1"); 
For<IMyObject>().Add<MyObjectType2>().Named("Type2"); 
For<IMyObject>().Add<MyObjectType3>().Named("Type3"); 

I хотел бы вставить все экземпляры в конструктор, чтобы я мог получить любой именованный экземпляр. Пример кода (производит StructureMap исключение):

public class Example 
{ 
    private Dictionary<string, IMyObject> _workers; 

    public Example(Dictionary<string, IMyObject> workers) 
    { 
    _workers = workers; 
    } 

    public void DoSomeStuff(string mode) 
    { 
    var worker = _workers[mode]; 
    worker.DoStuff(); 
    } 
} 

Мои рассуждения для этого подхода заключается в том, чтобы обеспечить внешнюю конфигурацию, чтобы указать, каким-то следует рассматривать (в «режиме» выше примере будет соответствовать именованного экземпляра).

Фактическое исключение состоит в следующем:

StructureMap.StructureMapException occurred 
    ErrorCode=202 
    HResult=-2146232832 
    Message=StructureMap Exception Code: 202 
No Default Instance defined for PluginFamily 

Я знаю, что я могу использовать контейнер StructureMap в моем методе DoSomeStuff для того, чтобы восстановить именованный экземпляр, однако, это что-то анти-паттерна ,

Так прояснить мой вопрос:

  • Могу ли я вводить словарь (или другой коллекции) именованных экземпляров, так что я могу обращаться к ним по имени?

Надеюсь, это ясно, просьба прокомментировать, если потребуется дополнительное объяснение.

  • C#: 4,0
  • StructureMap: 2.5.4.0

Спасибо,

Graeme

ответ

2

Вместо введения словаря, это могло бы быть лучше, чтобы ввести Func<string, IMyObject> вместо. Это предотвращает StructureMap от необходимости создавать все IMyObject экземпляры со всеми их зависимостями, в то время как только один из них действительно нужно использовать:

public class Example 
{ 
    private Func<string, IMyObject> _workers; 
    public Example(Func<string, IMyObject> workers) 
    { 
    _workers = workers; 
    } 

    public void DoSomeStuff(string mode) => _workers(mode).DoStuff(); 
} 

Вы можете зарегистрировать свой Example следующим образом:

For<Example>() 
    .Use(() => new Example(mode => container.GetInstance<IMyObject>(instanceKey: mode))); 
+0

Благодарности @Steven за время, чтобы ответить. Один экземпляр примера будет использовать все экземпляры IMyObject в какой-то момент путем повторных вызовов. Класс класса в основном отвечает за правильность реализации IMyObject. Я знаю, что я мог бы «обновить» словарь в реестре, когда запрашивается пример calss, но надеется, что есть более элегантное решение. – GinjaNinja

+0

@GinjaNinja: Я нахожу, что решение представлено самым элегантным. Почему это решение не работает для вас? – Steven

+0

Извиняюсь, я, возможно, немного поспешил туда. Ваше решение работает для меня, и я приму ответ. Я надеялся, что есть встроенный способ получить все экземпляры, представленные в какой-то коллекции, без дополнительной «проводки» класса example. Как побочный вопрос, знаете ли вы, как обеспечить создание только одного объекта каждой реализации IMyObject? – GinjaNinja