I want to register the following dummy IRequestPreProcessor (Mediator 3)
public class IdentifyUserTypeCommandHandler : IRequestPreProcessor<RegisterUserCommand>
{
private readonly IOptions<TecApiOptions> _options;
public IdentifyUserTypeCommandHandler(IOptions<TecApiOptions> options)
{
_options = options;
}
public async Task Process(RegisterUserCommand request)
{
request.Type = "internal";
await Task.FromResult(true);
}
}
To do so, I have my container setup to map IRequestPreProcessor to my concrete implementation IdentifyUserTypeCommandHandler
// Pipeline engine used internally to simplify controllers
services.AddMediatR();
// Pre-processors
services.AddTransient(typeof(IRequestPreProcessor<RegisterUserCommand>), typeof(IdentifyUserTypeCommandHandler));
// Registers command validator
services.AddTransient(typeof(IValidator<RegisterUserCommand>), typeof(RegisterUserCommandValidator));
// Registers generic behaviors
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(Pipeline<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
As soon as I run the code, I get the following exception
System.ArgumentException: Open generic service type 'MediatR.Pipeline.IRequestPreProcessor`1[TRequest]' requires registering an open generic implementation type.
I want to run this pre-processor only for commands of type RegisterUserCommand. Any idea on how I can solve this issue?
FYI for the records,
public class LoggingBehavior<TCommand, TResponse> : IPipelineBehavior<TCommand, TResponse>
{
private readonly ILogger _logger;
public LoggingBehavior(ILoggerFactory loggerFactory)
{
_logger = loggerFactory?.CreateLogger(typeof(TCommand).Name) ?? throw new ArgumentNullException(nameof(loggerFactory));
}
public async Task<TResponse> Handle(TCommand request, RequestHandlerDelegate<TResponse> next)
{
try
{
_logger.LogInformation(LoggingEvents.RUN_HANDLER, $"Handling '{typeof(TCommand).Name}'");
var response = await next();
_logger.LogInformation(LoggingEvents.RUN_HANDLER, $"Handled '{typeof(TResponse).Name}'");
return response;
}
catch (Exception e)
{
_logger.LogError(
LoggingEvents.RUN_HANDLER_EXCEPTION, e,
$"An error occured while processing pipeline '{GetType().Name}' [{typeof(TCommand).Name} >> {typeof(TResponse).Name}]");
throw;
}
}
}
Thank you, Regards, Seb
So after talking to the lib's creator, it seems that Pre & Post processors must have a generic definition.
public class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>
OR
public class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
src: Examples
The <TRequest>
and <TRequest, TResponse>
are required when creating a new Pre/Post processors. Now the 1 000 000$ dollars question I will try to answer later:
How do we specialize processors so they deal with a specific set of requests/commands (without having to check request type)...