gpt4 book ai didi

c# - Autofac - 注册多个装饰器

转载 作者:可可西里 更新时间:2023-11-01 02:58:45 25 4
gpt4 key购买 nike

鉴于以下情况:

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

它会连接所有命令处理程序并按照给定的顺序添加装饰器。

关于c# - Autofac - 注册多个装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17438570/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com