簡體   English   中英

Autofac - 注冊多個裝飾器

[英]Autofac - Register multiple decorators

鑒於以下內容:

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

public class MoveCustomerCommand
{

}

public class MoveCustomerCommandHandler : ICommandHandler<MoveCustomerCommand>
{
    public void Handle(MoveCustomerCommand command)
    {
        Console.WriteLine("MoveCustomerCommandHandler");
    }
}

public class TransactionCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> _decorated;

    public TransactionCommandHandlerDecorator(ICommandHandler<TCommand> decorated)
    {
        _decorated = decorated;
    }

    public void Handle(TCommand command)
    {
        Console.WriteLine("TransactionCommandHandlerDecorator - before");
        _decorated.Handle(command);
        Console.WriteLine("TransactionCommandHandlerDecorator - after");
    }
}

public class DeadlockRetryCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> _decorated;

    public DeadlockRetryCommandHandlerDecorator(ICommandHandler<TCommand> decorated)
    {
        _decorated = decorated;
    }

    public void Handle(TCommand command)
    {
        Console.WriteLine("DeadlockRetryCommandHandlerDecorator - before");
        _decorated.Handle(command);
        Console.WriteLine("DeadlockRetryCommandHandlerDecorator - after");
    }
}

我可以使用以下代碼使用TransactionCommandHandlerDecorator修飾MoveCustomerCommandHandler

var builder = new ContainerBuilder();

builder.RegisterAssemblyTypes(typeof(MoveCustomerCommandHandler).Assembly)
    .As(type => type.GetInterfaces()
    .Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(ICommandHandler<>)))
    .Select(interfaceType => new KeyedService("commandHandler", interfaceType)));

builder.RegisterGenericDecorator(
        typeof(TransactionCommandHandlerDecorator<>),
        typeof(ICommandHandler<>),
        fromKey: "commandHandler");

var container = builder.Build();

var commandHandler = container.Resolve<ICommandHandler<MoveCustomerCommand>>();
commandHandler.Handle(new MoveCustomerCommand());

哪個會輸出:

TransactionCommandHandlerDecorator - before  
MoveCustomerCommandHandler 
TransactionCommandHandlerDecorator - after 

如何使用DeadlockRetryCommandHandlerDecorator裝飾TransactionCommandHandlerDecorator ,以生成以下輸出

DeadlockRetryCommandHandlerDecorator- before
TransactionCommandHandlerDecorator - before  
MoveCustomerCommandHandler 
TransactionCommandHandlerDecorator - after 
DeadlockRetryCommandHandlerDecorator- after

@nemesv已經回答了這個問題,但是我想我會補充一點,你可以添加一些簡單的輔助方法來使許多通用裝飾器連接起來,減少Autofac的痛苦:

    private static void RegisterHandlers(
        ContainerBuilder builder, 
        Type handlerType,
        params Type[] decorators)
    {
        RegisterHandlers(builder, handlerType);

        for (int i = 0; i < decorators.Length; i++)
        {
            RegisterGenericDecorator(
                builder,
                decorators[i],
                handlerType,
                i == 0 ? handlerType : decorators[i - 1],
                i != decorators.Length - 1);
        }
    }

    private static void RegisterHandlers(ContainerBuilder builder, Type handlerType)
    {
        builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .As(t => t.GetInterfaces()
                    .Where(v => v.IsClosedTypeOf(handlerType))
                    .Select(v => new KeyedService(handlerType.Name, v)))
            .InstancePerRequest();
    }

    private static void RegisterGenericDecorator(
        ContainerBuilder builder,
        Type decoratorType,
        Type decoratedServiceType,
        Type fromKeyType,
        bool hasKey)
    {
        var result = builder.RegisterGenericDecorator(
           decoratorType,
           decoratedServiceType,
           fromKeyType.Name);

        if (hasKey)
        {
            result.Keyed(decoratorType.Name, decoratedServiceType);
        }
    }

如果將這些方法粘貼到您正在配置Autofac的位置,那么您可以這樣做:

    RegisterHandlers(
        builder, 
        typeof(ICommandHandler<>),
        typeof(TransactionCommandHandlerDecorator<>),
        typeof(ValidationCommandHandlerDecorator<>));

它將連接所有命令處理程序並按給定的順序添加裝飾器。

您只需將“TransactionCommandHandlerDecoratored” ICommandHandler注冊為Keyed服務,並在注冊第二個DeadlockRetryCommandHandlerDecorator時使用該新密鑰:

builder.RegisterGenericDecorator(
        typeof(TransactionCommandHandlerDecorator<>),
        typeof(ICommandHandler<>),
        fromKey: "commandHandler")
        .Keyed("decorated", typeof(ICommandHandler<>));

builder.RegisterGenericDecorator(
        typeof(DeadlockRetryCommandHandlerDecorator<>),
        typeof(ICommandHandler<>),
        fromKey: "decorated");

您將獲得以下輸出:

DeadlockRetryCommandHandlerDecorator - before
TransactionCommandHandlerDecorator - before
MoveCustomerCommandHandler
TransactionCommandHandlerDecorator - after
DeadlockRetryCommandHandlerDecorator - after

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM