[英]Autofac - Register multiple decorators
Given the following: 鉴于以下内容:
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");
}
}
I can decorate the MoveCustomerCommandHandler
with a TransactionCommandHandlerDecorator
using the following code: 我可以使用以下代码使用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());
Which will output : 哪个会输出:
TransactionCommandHandlerDecorator - before
MoveCustomerCommandHandler
TransactionCommandHandlerDecorator - after
How can I also decorate the TransactionCommandHandlerDecorator
with the DeadlockRetryCommandHandlerDecorator
, to generate the following output 如何使用DeadlockRetryCommandHandlerDecorator
装饰TransactionCommandHandlerDecorator
,以生成以下输出
DeadlockRetryCommandHandlerDecorator- before
TransactionCommandHandlerDecorator - before
MoveCustomerCommandHandler
TransactionCommandHandlerDecorator - after
DeadlockRetryCommandHandlerDecorator- after
@nemesv has already answered this question, however I just thought I'd add that you can add some simple helper methods to make wiring up lots of generic decorators less painful in Autofac: @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);
}
}
If you paste those methods into the place you're configuring Autofac, then you can just do this: 如果将这些方法粘贴到您正在配置Autofac的位置,那么您可以这样做:
RegisterHandlers(
builder,
typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>),
typeof(ValidationCommandHandlerDecorator<>));
And it will wire up all your command handlers and add the decorators in the order given. 它将连接所有命令处理程序并按给定的顺序添加装饰器。
You just need to register your "TransactionCommandHandlerDecoratored" ICommandHandler
as a Keyed
service and use that new key when registering your second DeadlockRetryCommandHandlerDecorator
: 您只需将“TransactionCommandHandlerDecoratored” ICommandHandler
注册为Keyed
服务,并在注册第二个DeadlockRetryCommandHandlerDecorator
时使用该新密钥:
builder.RegisterGenericDecorator(
typeof(TransactionCommandHandlerDecorator<>),
typeof(ICommandHandler<>),
fromKey: "commandHandler")
.Keyed("decorated", typeof(ICommandHandler<>));
builder.RegisterGenericDecorator(
typeof(DeadlockRetryCommandHandlerDecorator<>),
typeof(ICommandHandler<>),
fromKey: "decorated");
And you will get the following output: 您将获得以下输出:
DeadlockRetryCommandHandlerDecorator - before
TransactionCommandHandlerDecorator - before
MoveCustomerCommandHandler
TransactionCommandHandlerDecorator - after
DeadlockRetryCommandHandlerDecorator - after
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.