【问题标题】:How Can I Apply Conditional Decorator to a Command Handler with SimpleInjector?如何使用 SimpleInjector 将条件装饰器应用于命令处理程序?
【发布时间】:2016-02-04 10:51:22
【问题描述】:

我有以下命令处理程序接口:

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) {  }        
}

但是....我不一定要装饰所有命令处理程序,而只想装饰ICommandHandler&lt;TCommand&gt; IF 一个实例存在/注册IValidator&lt;TCommand&gt; 的具体类型的TCommand。注意IValidator&lt;TCommand&gt; 实例是在装饰器类的构造函数中注入的。

例如,如果我有一个命令处理程序:

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<>));

如果任何给定的ICommandHandler&lt;&gt; 不存在IValidator&lt;&gt; 的实例,这显然会失败。对于信息,assemblies 是用于注册泛型类的程序集的集合。

如果可能的话,我应该使用什么来注册装饰器/验证器以实现我想要做的事情?我不想切换使用 SimpleInjector。

此外,如果可能的话,这是推荐的还是违反了 SOLID 原则,甚至只是代码异味?

【问题讨论】:

    标签: c# .net simple-injector


    【解决方案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 存在的那种东西:-)

    【讨论】:

    • 不错的简单解决方案。
    • 另一种解决方案是将验证器注册为集合(可选地包装在复合材料中)。
    • 我总是使用这个条件解决方案,很好,快速和干净。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2015-02-01
    • 2019-07-02
    • 2011-05-06
    • 2020-11-30
    相关资源
    最近更新 更多