Dati i seguenti:autofac - registrare più decoratori
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");
}
}
posso decorare la MoveCustomerCommandHandler
con un TransactionCommandHandlerDecorator
utilizzando il seguente codice:
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());
che sarà in uscita:
TransactionCommandHandlerDecorator - before
MoveCustomerCommandHandler
TransactionCommandHandlerDecorator - after
Come posso decorare anche lo TransactionCommandHandlerDecorator
con DeadlockRetryCommandHandlerDecorator
, per generare il seguente output
DeadlockRetryCommandHandlerDecorator- before
TransactionCommandHandlerDecorator - before
MoveCustomerCommandHandler
TransactionCommandHandlerDecorator - after
DeadlockRetryCommandHandlerDecorator- after
Domanda aggiuntiva per punti extra: come si registra un decoratore condizionale in Autofac, ad esempio in base a un vincolo di tipo generico? – Steven
@Steven buona domanda, e non ne ho idea :) Questa è la prima volta che ho usato la funzione di decoratore in Autofac per rispondere a questa domanda, quindi devo cercarlo ma immagino che l'impletazione di default non sia così flessibile per fornire condizioni, ma puoi sempre scrivere il tuo 'IRegistrationSource' ... ma immagino ci sia un modo super semplice per farlo in SimpleInjector;) – nemesv
Lo chiedo perché spesso ottengo domande da sviluppatori che vogliono applicare questi pattern utilizzando altri contenitori rispetto a Simple Injector, ma sfortunatamente non sono in grado di fornire loro delle buone risposte - tranne ovviamente il consiglio di usare Simple Injector :-). Ma sì, hai ragione, questa è un'area in cui Simple Injector brilla davvero. – Steven