Open fmontazeri opened 2 years ago
This is an old post but reading it made me realize I was not filtering out my decorators at registration time, which I think is a good idea. Bellow, I outlined what worked for me.
public interface ICommandHandler<in TCommand, TResponse> where TCommand : ICommand where TResponse: class
{
Task<Result<TResponse>> Handle(TCommand command);
}
// Decorators
public class CommandExceptionHandlingBehavior<TCommand, TResult> : ICommandHandler<TCommand, TResult> where TCommand : ICommand where TResult : class
{
private ICommandHandler<TCommand, TResult> NextCommandHandler { get; }
public CommandExceptionHandlingBehavior(ICommandHandler<TCommand, TResult> nextCommandHandler)
{
NextCommandHandler = nextCommandHandler;
}
public async Task<Result<TResult>> Handle(TCommand command)
{
try
{
return await NextCommandHandler.Handle(command);
}
catch (QuotaExceededException ex)
{
return Result<TResult>.Failure(ex.AsError());
}
catch (Exception ex)
{
return Result<TResult>.Failure(new Error
{
Message = ex.Message,
Reference = NextCommandHandler.GetType().ToString(),
Type = Error.ErrorTypes.UnknownError
});
}
}
}
public class CommandValidationBehavior<TCommand, TResult> : ICommandHandler<TCommand, TResult> where TCommand : ICommand where TResult : class
{
private ICommandHandler<TCommand, TResult> NextCommandHandler { get; }
private IValidator<TCommand> Validator { get; }
public CommandValidationBehavior(ICommandHandler<TCommand, TResult> nextCommandHandler, IValidator<TCommand> validator)
{
NextCommandHandler = nextCommandHandler;
Validator = validator;
}
public async Task<Result<TResult>> Handle(TCommand command)
{
var errors = await Validator.ValidateAsync(command);
if (errors.Any())
{
return Result<TResult>.Failure(errors);
}
return await NextCommandHandler.Handle(command);
}
}
// IoC Configurations
services.Scan(scan => scan.FromCallingAssembly()
// First gather all the possible implementations of my commands and then filter out the decorators
.AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<,>)).Where(c => !c.IsAssignableTo(typeof(ICommandBehavior))))
.AsImplementedInterfaces()
.WithTransientLifetime()
);
services.Decorate(typeof(ICommandHandler<,>), typeof(CommandValidationBehavior<,>));
services.Decorate(typeof(ICommandHandler<,>), typeof(CommandExceptionHandlingBehavior<,>));
Hi dear, I want to decorate command handlers with decorator Pattern in an ASP.NET Core app. So I registered command handers first and then register decorators. But it doesn't work. I am using built-in IoC in ASP.NET Core and Scrutor. You can see them below.
Registration of command handlers and decorators
Could you tell me how can I do that , please? Thanks in advance