无法向 Mediatr 注册 IRequestPreProcessors
Unable to register IRequestPreProcessors with Mediatr
我想注册以下虚拟 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);
}
}
为此,我设置了容器以将 IRequestPreProcessor 映射到我的具体实现 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<,>));
一旦我 运行 代码,我就会得到以下异常
System.ArgumentException: Open generic service type 'MediatR.Pipeline.IRequestPreProcessor`1[TRequest]' requires registering an open generic implementation type.
我想 运行 此预处理器仅用于 RegisterUserCommand 类型的命令。知道如何解决这个问题吗?
仅供参考,
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;
}
}
}
谢谢,
问候,
塞布
所以在与 lib 的创建者交谈后,似乎 Pre & Post 处理器必须有一个通用定义。
public class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>
或
public class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
来源:Examples
创建新的 Pre/Post 处理器时需要 <TRequest>
和 <TRequest, TResponse>
。现在我稍后会尝试回答 1 000 000 美元的问题:
How do we specialize processors so they deal with a specific set of requests/commands (without having to check request type)...
如果您正在使用 services.AddMediatR()
确保注册内置行为:RequestPreProcessorBehavior
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.AddMediatR();
然后你的预处理器需要根据@Sebastien的回答有通用定义:
public class PingDecorator<TRequest> : IRequestPreProcessor<TRequest>
{
public Task Process(TRequest request)
{
return Unit.Task;
}
}
如果您希望预处理器仅用于特定请求:
public class PingDecorator<TRequest> : IRequestPreProcessor<TRequest> where TRequest:Ping
{
public Task Process(TRequest request)
{
request.Message = request.Message + " Decorated";
return Unit.Task;
}
}
最新版本内置注册,使用从程序集检索,无需注册。
请注意,我已经使用多个 IRequestPreProcessor 实现对其进行了测试,并且所有这些实现都按照它们在代码中编写的相同顺序工作。我认为这可能是一个语义错误,因为从逻辑上讲它不应该只有一个 RequestPreProcessor。
我想注册以下虚拟 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);
}
}
为此,我设置了容器以将 IRequestPreProcessor 映射到我的具体实现 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<,>));
一旦我 运行 代码,我就会得到以下异常
System.ArgumentException: Open generic service type 'MediatR.Pipeline.IRequestPreProcessor`1[TRequest]' requires registering an open generic implementation type.
我想 运行 此预处理器仅用于 RegisterUserCommand 类型的命令。知道如何解决这个问题吗?
仅供参考,
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;
}
}
}
谢谢, 问候, 塞布
所以在与 lib 的创建者交谈后,似乎 Pre & Post 处理器必须有一个通用定义。
public class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>
或
public class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
来源:Examples
创建新的 Pre/Post 处理器时需要 <TRequest>
和 <TRequest, TResponse>
。现在我稍后会尝试回答 1 000 000 美元的问题:
How do we specialize processors so they deal with a specific set of requests/commands (without having to check request type)...
如果您正在使用 services.AddMediatR()
确保注册内置行为:RequestPreProcessorBehavior
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.AddMediatR();
然后你的预处理器需要根据@Sebastien的回答有通用定义:
public class PingDecorator<TRequest> : IRequestPreProcessor<TRequest>
{
public Task Process(TRequest request)
{
return Unit.Task;
}
}
如果您希望预处理器仅用于特定请求:
public class PingDecorator<TRequest> : IRequestPreProcessor<TRequest> where TRequest:Ping
{
public Task Process(TRequest request)
{
request.Message = request.Message + " Decorated";
return Unit.Task;
}
}
最新版本内置注册,使用从程序集检索,无需注册。 请注意,我已经使用多个 IRequestPreProcessor 实现对其进行了测试,并且所有这些实现都按照它们在代码中编写的相同顺序工作。我认为这可能是一个语义错误,因为从逻辑上讲它不应该只有一个 RequestPreProcessor。