2015-03-28 2 views
2

Я пытаюсь применить подход this, чтобы сделать проверку. Я создал следующие интерфейсы, и я использую Ninject как мой DI контейнерРисунок декоратора с Ninject

public interface ICommandHandler<TCommand> 
    { 
     void Handle(TCommand command); 
    } 

public interface IValidator<T> 
{ 
    IEnumerable<ValidationResult> Validate(T command); 
} 

public class ValidationCommandHandlerDecorator<T>:ICommandHandler<T> 
{ 
    private readonly ICommandHandler<T> _decoratee; 
    private readonly IValidator<T> _validator; 

    public ValidationCommandHandlerDecorator(ICommandHandler<T> decoratee,IValidator<T> validator) 
    { 
     _decoratee = decoratee; 
     _validator = validator; 
    } 
    public void Handle(T command) 
    { 
     this._validator.Validate(command); 
     this._decoratee.Handle(command); 
    } 
} 

public class SaveNewOsiRequestController : ApiController 
{ 
    private readonly ICommandHandler<OsiRequest> _osiRequestSaveHandler; 

    public SaveNewOsiRequestController(ICommandHandler<OsiRequest> osiRequestSaveHandler) 
    { 
     _osiRequestSaveHandler = osiRequestSaveHandler; 
    } 
} 

И следующее, как я инъекционный конкретные классы в контроллер:

 kernel.Bind(typeof (IValidator<>)).To(typeof (OsiRequestValidator)); 

     kernel.Bind(typeof (ICommandHandler<>)) 
      .To(typeof (SaveOsiRequestCommandHandler)) 
      .WhenInjectedInto(typeof (ValidationCommandHandlerDecorator<>)); 

     kernel.Bind(typeof (ICommandHandler<>)) 
      .To(typeof (ValidationCommandHandlerDecorator<>)) 
      .WhenInjectedInto(typeof(SaveNewOsiRequestController)); 

код работает отлично без любая проблема. Однако вопрос в том, как я могу сделать ту же инъекцию для другого контроллера с Ninject? Чтобы сделать это просто я хочу, чтобы ввести другой Validator и Другой CommandHandler к другому Controller вроде этого:

 kernel.Bind(typeof (IValidator<>)).To(typeof (ANOTHER_Validator)); 

     kernel.Bind(typeof (ICommandHandler<>)) 
      .To(typeof (ANOTHER_CommandHandler)) 
      .WhenInjectedInto(typeof (ValidationCommandHandlerDecorator<>)); 

     kernel.Bind(typeof (ICommandHandler<>)) 
      .To(typeof (ValidationCommandHandlerDecorator<>)) 
      .WhenInjectedInto(typeof(ANOTHER_RequestController)); 

ответ

1

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

Для этого, вы можете так же легко сделать это:

kernel.Bind<IValidator<OsiRequest>>().To<OsiRequestValidator>(); 

kernel.Bind<ICommandHandler<OsiRequest>() 
     .To<SaveOsiRequestCommandHandler>() 
     .WhenInjectedInto<ValidationCommandHandlerDecorator<OsiRequest>>(); 

kernel.Bind<ICommandHandler<OsiRequest>() 
     .To<ValidationCommandHandlerDecorator<OsiRequest>() 
     .WhenInjectedInto<SaveNewOsiRequestController>(); 

Тогда каждый дополнительный будет:

kernel.Bind<IValidator<DifferentRequest>>().To<DifferentValidator>(); 

kernel.Bind<ICommandHandler<DifferentRequest>() 
     .To<DifferentRequestCommandHandler>() 
     .WhenInjectedInto<ValidationCommandHandlerDecorator<DifferentRequest>>(); 

kernel.Bind<ICommandHandler<DifferentRequest>() 
     .To<ValidationCommandHandlerDecorator<DifferentRequest>() 
     .WhenInjectedInto<DifferentRequestController>(); 

Вы можете изменить последнее связывание, так что вы не должны объявить его для каждого типа:

kernel.Bind(typeof (ICommandHandler<>)) 
     .To(typeof (ValidationCommandHandlerDecorator<>)) 
     .WhenInjectedInto<ApiController>(); 
+0

Большое спасибо Эрик. Это была спасательная жизнь. Просто вопрос. Я следую правильному подходу? Является ли инъекция конкретным конкретным классам в общий интерфейс? Исправлена ​​ли вообще с архитектурной точки зрения? –

+0

@MehrdadKamelzadeh - Ну, когда вам нужны конкретные экземпляры в определенных ситуациях, у вас нет большого выбора. Вы могли бы упростить это, если бы смогли выяснить способ вызова общей реализации только с типами интерфейса, но ваши реализации, похоже, не делают этого. Кроме того, вы можете повторно использовать последнее связывание, так как это общее. См. Мое обновление. Это использует тот факт, что Ninject будет ходить по базовым классам при использовании '.WhenInjectedInto()' –

+0

@MehrdadKamelzadeh - но остальные два должны оставаться конкретными, потому что нет возможности автоматически сопоставить общий тип с определенным типом. –

Смежные вопросы