2016-02-04 80 views
3

我有以下命令處理程序接口:如何使用SimpleInjector將條件裝飾器應用於命令處理程序?

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

我修飾這個接口的實例有以下具體類:

public class ValidationCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> 
    where TCommand : ICommand 
{ 
    public ValidationCommandHandlerDecorator(
     IValidator<TCommand> validator, 
     ICommandHandler<TCommand> handler) 
    { 
    } 

    public void Handle(TCommand command) { }   
} 

但....我並不想裝飾ALL命令處理程序,只想裝飾ICommandHandler<TCommand>如果實例存在/註冊爲IValidator<TCommand>,則爲TCommand的具體類型。請注意,IValidator<TCommand>實例是在裝飾器類的構造函數中注入的。

舉例來說,如果我有一個命令處理程序:

public class CreateFooCommandHandler : ICommandHandler<CreateFooCommand> 

我只是想裝飾,如果我有以下實例註冊:

public class CreateFooCommandValidator : IValidator<CreateFooCommand> 

如果CreateFooCommandValidator不存在,我不我不想用ValidationCommandHandlerDecorator來裝飾CreateFooCommandHandler

我使用與SimpleInjector註冊時執行以下操作:

var container = new Container(); 

container.Register(typeof(ICommandHandler<>), assemblies); 
container.Register(typeof(IValidator<>), assemblies); 
container.RegisterDecorator(
    typeof(ICommandHandler<>), 
    typeof(ValidationCommandHandlerDecorator<>)); 

顯然,如果沒有IValidator<>目前對於任何給定ICommandHandler<>實例失敗。有關信息assemblies是用於註冊泛型類的程序集的集合。

如果可能的話,我應該使用什麼來註冊裝飾器/驗證器來實現我想要做的事情?我不想從使用SimpleInjector切換。

此外,如果有可能,這是推薦的還是違反了固體原則,甚至只是代碼味道?

回答

1

您可以通過分析容器中的註冊並決定是否裝飾每個實例來註冊一個條件裝飾器,但我不認爲這是最好的選擇。最簡單的解決方案是定義並註冊,其中實際IValidator不存在的情況下,回退NullValidator ...

public class NullValidator<TCommand> : IValidator<TCommand> where TCommand : ICommand 
{ 
    public void Validate(TCommand command) 
    { 
    } 
} 

註冊爲條件

var container = new Container(); 

container.Register(typeof(ICommandHandler<>), assemblies); 
container.Register(typeof(IValidator<>), assemblies); 
container.RegisterConditional(
    typeof(IValidator<>), 
    typeof(NullValidator<>), 
    c => !c.Handled); 
container.RegisterDecorator(
    typeof(ICommandHandler<>), 
    typeof(ValidationCommandHandlerDecorator<>)); 

container.Verify(); 

我不不想使用SimpleInjector進行切換。

好男人!

此外,如果有可能,這是推薦的還是違反了SOLID原則,甚至只是代碼味道?

這正是那種東西RegisterConditional存在:-)

+0

尼斯簡單的解決方案。 – Graham

+0

另一種解決方案是將驗證器註冊爲集合(可選地包裝在組合中)。 – Steven

+0

我總是使用這個條件解決方案,很好,快速和乾淨。 :-) – janhartmann

相關問題