2015-02-06 1 views
0

У меня есть структура вроде:Как вводить различную зависимость, зависит от имени аргумента, используя Windsor

public class Processor<T> 
{ 
    public Processor(IManager<T> xmlManager, IManager<T> memoryManager) 
    { 

    } 
} 

public interface IManager<T> 
{ 

} 

public class Manager<T> : IManager<T> 
{ 
    private readonly IProvider _provider; 

    public Manager(IProvider provider) 
    { 
     _provider = provider; 
    } 
} 

public interface IProvider { } 

public class XmlProvider : IProvider { } 

public class MemoryProvider : IProvider { } 

мне нужно вводить в класс Processor два экземпляра класса Manager, но с различными инъекциями. Так жёстко мне нужно:

var p = new Processor<T>(new Manager<T>(new XmlProvider()) , new Manager<T>(new MemoryProvider())) 

Кроме того, мне нужно решить это использование открытого родового типа T.

Я не могу понять, как настроить контейнер для управления этим. Я знаю, что есть директива .DependsOn(Property.ForKey("xmlManager").Eq(). Но я не могу понять, что писать в Eq(), за исключением жестко заданной реализации. У поставщиков есть свои зависимости. Поэтому не стоит писать .Eq(new Manager<T>(new XmlProvide(new OtherInjection(new AnotherOne())))). И там я не могу использовать открытый родовой.

UPD 1 Mr NightOwl888. О логике. Один поставщик предназначен для хранения данных в кэше памяти. Второй поставщик предназначен для хранения данных, хранящих данные в xml-файлах. Какая-то модель уровня 2 уровня. Он не сломается, если я поменяю два параметра (например, Стивен сказал), но он будет работать не так, как он был спроектирован (из-за различной скорости извлечения информации).

+2

Вы можете использовать вложение свойств: http://stackoverflow.com/questions/5030431/castle-windsor-map-named-component-to-specific-property или посмотреть здесь http://stackoverflow.com/questions/11325699/castle -windsor-how-to-map-named-instance-in-constructor-injection – Ric

+1

Что произойдет, если вы случайно замените два параметра? Разве ваш «процессор» сломается? Если это так, вы нарушаете Принцип замещения Лискова, и вы, возможно, захотите переосмыслить свой дизайн. – Steven

+2

Я согласен с @Steven. Весь смысл создания абстракции (интерфейса) заключается в том, что вы можете заменить реализацию без «Процессора», зная, какой конкретный тип «IManager » вы имеете в виду. С вашей конструкцией «Процессор» знает эти детали, и если третий тип «IManager » вводится позже, это является нарушением изменений для «Процессора». Требует ли 'Процессор' * более одного *' IManager 'для выполнения или он * выбирает один * на основе условия? «Процессор» нарушает принцип единой ответственности, включив эту логику. Также неясно, какая логика от дизайна. – NightOwl888

ответ

0

Я не работал с Виндзор, но общее решение выглядит как

public class ManagerFactory // register it in container 
{ 
    public IManager<T> Create<T>(IProvider provider) { return ... } 
} 

public class Processor<T> 
{ 
    public Processor(ManagerFactory factory, IEnumerable<IProvider> providers) 
    { 
     myManagers = providers.Select(provider => factory.Create<T>(provider).ToList(); 
    } 
} 

Как правило, вы можете зарегистрировать множество реализаций некоторого интерфейса (в вашем случае для IProvider), поэтому контейнер может придать им все