簡體   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