0

我想注册以下虚拟 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:开放通用服务类型“MediatR.Pipeline.IRequestPreProcessor`1[TRequest]”需要注册开放通用实现类型。

我只想为 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;
        }
    }
}

谢谢, 问候, Seb

4

3 回答 3

3

因此,在与 lib 的创建者交谈之后,似乎 Pre & Post 处理器必须有一个通用的定义。

public class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>

或者

public class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest>

src:示例

创建新的前置/后置处理器时需要和<TRequest><TRequest, TResponse>现在我稍后会尝试回答 1 000 000 美元的问题:

我们如何专门处理处理器,以便它们处理一组特定的请求/命令(无需检查请求类型)......

于 2017-07-19T07:14:40.380 回答
3

如果你正在使用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;
    }
}
于 2017-09-01T01:33:56.707 回答
1

最新版本已内置使用从程序集中检索的注册,无需注册。请注意,我已经使用多个 IRequestPreProcessor 实现对其进行了测试,并且它们都按照它们在代码中编写的顺序工作。我认为这可能是一个语义错误,因为从逻辑上讲它不应该只有一个 RequestPreProcessor。

于 2021-08-16T10:39:46.447 回答