繁体   English   中英

如何使用structuremap asp.net mvc注册带有可选参数的可选装饰器或装饰器?

[英]How to register an optional decorator or decorator with optional parameters using structuremap asp.net mvc?

我在我的应用程序中实施了一个CQRS方法,受到这篇精彩文章的影响很大: https ://cuttingedge.it/blogs/steven/pivot/entry.php?id = 9 我的命令和处理程序代码的设置与文章相同,而且该部分运行良好。 当我尝试实现一个装饰器类来处理命令的验证时,我的问题出现了。 简单的命令处理接口如下所示:

public interface ICommand
{
}

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

然后对于验证装饰我有:

public class ValidationCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> where TCommand : CommandBase
{
    private readonly ICommandHandler<TCommand> _decoratedCommandHandler;
    private readonly ICommandValidator<TCommand> _commandValidator;

    public ValidationCommandHandlerDecorator(ICommandHandler<TCommand> decoratedCommandHandler, ICommandValidator<TCommand> commandValidator)
    {
        _decoratedCommandHandler = decoratedCommandHandler;
        _commandValidator = commandValidator;
    }

    public void Handle(TCommand command)
    {
        if (_commandValidator != null)
        {
            var validationResult = _commandValidator.Validate(command);

            if (validationResult != null)
            {
                command.Success = false;
                command.Errors = validationResult;
                return;
            }
        }

        _decoratedCommandHandler.Handle(command);
        command.Success = true;
    }
}    

它使用接口来定义验证器:

public interface ICommandValidator<TCommand>
{
    IEnumerable<string> Validate(TCommand command);
}

CommandBase是一个简单的基类,它允许我存储命令的成功或失败以及失败时发生的错误。 我更喜欢这种方法作为抛出异常的替代方法。 所有命令都将继承此基类。

public abstract class CommandBase : ICommand
{
    public bool Success { get; set; }
    public IEnumerable<string> Errors { get; set; }
}

这些都连接到结构映射注册表中的IoC容器:

public class CommandRegistry : Registry
{
    public CommandRegistry()
    {
        Scan(s =>
        {
            s.AssemblyContainingType<CommandBase>();
            s.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
            s.ConnectImplementationsToTypesClosing(typeof(ICommandValidator<>));
            s.WithDefaultConventions();

            For(typeof(ICommandHandler<>)).DecorateAllWith(typeof(ValidationCommandHandlerDecorator<>));
        });
    }
}

现在,因为我为每个ICommandHandler注册了装饰器,如果我有一个不需要验证器且没有定义验证器的命令,则找不到ValidationCommandHandlerDecorator<TCommand>类的ICommandValidator<TCommand> _commandValidator私有字段因为它当然不存在并且总是会抛出结构图错误:

“没有注册默认实例,无法自动确定类型'ICommandValidator'没有为ICommandValidator指定配置”

结构映射中是否有一种方法可以定义如何构造ValidationCommandHandlerDecorator ,以便在不存在时使用某种类型的默认验证器,而不必依赖于类中的容器或必须创建IValidateableCommandHandler<TCommand>用验证器处理命令的接口?

谢谢。

如果有人遇到这个问题,我想出的解决方案是将DefaultCommandValidator类添加为Null Object模式类:

public class DefaultCommandValidator<TCommand> : ICommandValidator<TCommand> where TCommand : CommandBase
{
    public IEnumerable<string> Validate(TCommand command)
    {
        return Enumerable.Empty<string>();
    }
}

然后将此行添加到结构映射注册表:

For(typeof(ICommandValidator<>)).Use(typeof(DefaultCommandValidator<>));

我不知道这个结构映射语法实际上只会使用默认实例,如果它找不到ICommandValidator<TCommand>的具体实现。 现在,如果我没有验证器,我只是不添加验证器,而DefaultCommandValidator<TCommand>实例用于返回空/成功验证。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM