Замок Виндзор - Как отобразить именованный экземпляр в конструктор инъекций

может быть, это легко, но поиск в Интернете уже вызывает у меня головную боль

вот проблема:

interface IValidator
{
    void Validate(object obj);
}

public class ValidatorA : IValidator
{
    public void Validate(object obj) { }
}

public class ValidatorB : IValidator
{
    public void Validate(object obj) { }
}


interface IClassA { }
interface IClassB { }

public class MyBaseClass
{
    protected IValidator validator;

    public void Validate()
    {
        validator.Validate(this);
    }
}

public class ClassA : MyBaseClass, IClassA
{
    //problem: validator should ValidatorA
    public ClassA(IValidator validator) { }
}

public class ClassB : MyBaseClass, IClassB
{
    //problem: validator should ValidatorB
    public ClassB(IValidator validator) { }
}

public class OtherClass
{
    public OtherClass(IClassA a, IClassB b) { }
}


//on Main
var oc = container.Resolve<OtherClass>();

Любая идея?

EDIT

Я зарегистрировалValidatorA а такжеValidatorB сNamedТеперь проблема в том, как Castle Windsor может правильно ввести эти валидаторы вClassA а такжеClassB, Есть способ сделать это? или есть лучшее решение?

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

Validator is a complex object, sometime should connect to database, so I MUST pass interface instead of implementation to constructor for unit testing reason. No way to use different interface for any of Validator, because the only method that i used is Validate I think MyBaseClass.Validate() a common template method pattern isn't it?
 Jack Hughes04 июл. 2012 г., 13:16
Создайте интерфейс для ClassA и ClassB, например, IClassAValidator, который наследуется от IValidator и больше ничего не добавляет. Затем получите валидаторы для реализации конкретного интерфейса. ClassA может затем вставить в него IClassAValidator и передать IValidator в MyBaseClass.
 ktutnik04 июл. 2012 г., 11:36
обновил код, так что единственное, что мне действительно нужно, этоValidate метод
 Jacek Gorgoń04 июл. 2012 г., 11:19
Если ClassA требует особой реализации IValidator, то дизайн неправильный, поскольку интерфейс не предоставляет полезной абстракции.
 Damian Leszczyński - Vash04 июл. 2012 г., 10:59
Ваше описание проблемы является абстрактным.
 ktutnik04 июл. 2012 г., 11:25
@Jacek Grogon, нет, мне нужен толькоValidate метод, на самом деле есть базовый класс ClassA и ClassB, который называетсяValidate метод. но я не пишу это здесь, чтобы скрыть сложность.

Ответы на вопрос(2)

ClassA сValidatorA, ClassB сValidatorB) как независимые типы в общий контейнер. Это бессмысленно. Если вы должны полагаться на тесную связь, как это, забудьте об внедрении зависимостей в этом отношении и просто жестко ссылайтесь на типы.

Это имело бы больше смысла, если бы вы могли реализовать общий валидатор для всех классов. Например, возложите на классы ответственность за предоставление правил проверки иValidator просто применять правила. Или, возможно, просто включите всю проверку в ваши классы, что, пожалуй, самый разумный сценарий здесь.

MyBaseClass.Validate() похоже на инверсию управления, но не на шаблонный метод.

 ktutnik04 июл. 2012 г., 14:31
спасибо за ответ, да, класс был парой, но процесс повторяется, на самом деле есть задачи вMyBaseClass.Validate(): 1. Получить ошибки отvalidator.Validate(this)2. ОтправьтеDataErrorEvent 3. ИзменитьHasError Свойство (вот почему я называю это tempalte метод) все эти задачи должны быть выполнены ассинхронным способом. было бы плохой идеей сделать это в каждом ClassA и ClassB, верно?
 04 июл. 2012 г., 15:10
Я имею в виду удалить Validator * и поместить эту логику в Class * .ValidateCore () и вызвать ее в MyBaseClass.Validate (). Что именно вы тестируете? Почему ValidatorA подключается к базе данных? Дайте больше контекста.
 ktutnik04 июл. 2012 г., 14:53
если я не msitaken, вы имеете в видуValidatorA внутриClassA и сделать новый методValidateCore затем позвонитеValidateCore отMyBaseClass.Validate() право?. я думаю, что не могу этого сделать, потому что невозможно провести модульное тестирование, гдеValidatorA или жеValidatorB в любом случае следует подключиться к базе данных.
 ktutnik04 июл. 2012 г., 15:23
ClassA или ClassB должны содержать только логику представления (состояние кнопки, selectedIndex выпадающего списка и т. Д.), В действительности необходимо проверить свою логику вне вызова базы данных, в некоторых случаях Validator подключается к базе данных для получения информации, если какое-либо свойство соответствует конкретному состояние данных или нет? если я удаляю Validator и выполняю проверку внутри него, чтобы мое модульное тестирование подключалось к базе данных, и я думаю, что это не очень хорошая идея, как вы думаете, я использовал класс validator? кстати .. еще раз спасибо, я очень ценю ваше время, чтобы попытаться решить мою проблему
 04 июл. 2012 г., 14:40
Если так тоValidate() действительно шаблонный метод. Тем не менее, почему бы не положить метод ингредиентов, скажем,ValidateCore() вClassA и не вValidatorA? Если он повторяется, поместите его вMyBaseClass, ИзвлечениеValidator Класс добавляет больше сложности и мешает ясности.
Решение Вопроса

просто сосредоточив внимание на конфигурации контейнера Windsor:

Если вы зарегистрировали несколько именованных реализаций для данного интерфейса (IValidator), вы можете указать, какой из них вы хотите использовать при регистрации классов потребителей (ClassA, ClassB) с использованиемServiceOverrides:

Следующие поставщики конфигурации контейнераOtherClass сClassA экземпляр сValidatorA а такжеClassB экземпляр сValidatorB:

var container = new WindsorContainer();

container.Register(Component.For<IClassA>().ImplementedBy<ClassA>()
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorA")));
container.Register(Component.For<IClassB>().ImplementedBy<ClassB>()
    .DependsOn(ServiceOverride.ForKey<IValidator>().Eq("ValidatorB")));

container.Register(Component.For<IValidator>().ImplementedBy<ValidatorA>()
    .Named("ValidatorA"));
container.Register(Component.For<IValidator>().ImplementedBy<ValidatorB>()
    .Named("ValidatorB"));

container.Register(Component.For<OtherClass>().ImplementedBy<OtherClass>());

var oc = container.Resolve<OtherClass>();
 ktutnik04 июл. 2012 г., 17:18
спасибо, это то, что я хочу. дело закрыто

Ваш ответ на вопрос