如何在 Mediatr 中为所有请求定义一个特定的异常处理程序

Wim*_*uts 4 c# autofac mediatr asp.net-core

我在 ASP.NET core 项目中使用 Mediatr 来处理所有请求。我实现了几个请求/响应/处理程序。它们中的每一个都可以抛出一个特定的异常,我们将其称为“MyException”类。我将异常处理程序定义为

    public class MyExceptionHandler : RequestExceptionHandler<MyRequest<MyResponse>, MyResponse, MyException>
    {
        protected override void Handle(MyRequest<MyResponse> request, MyException exception, RequestExceptionHandlerState<MyResponse> state)
        {
            MyResponse response = new MyResponse();
            //Set some specific properties here in the response to indicate an error occurred
            state.SetHandled(response);
        }
    }
Run Code Online (Sandbox Code Playgroud)

我将此异常处理程序添加到 (Autofac) 依赖项容器中,如果我在 MyRequest 和 MyResponse 的 MyHandler 中抛出 MyException,则该异常处理程序有效。但是,我有数十个请求、响应和相应的处理程序。那么我如何为所有这些异常注册这个特定异常的异常处理程序(注意:所有响应都派生自同一个基类)。它尝试了类似下面的内容,但是,没有被调用。它仅在我给出实际类型时才有效,但这意味着我必须为每种类型创建一个异常处理程序,这远远不切合实际。关于如何解决这个问题有什么想法吗?

    public class MyExceptionHandler : RequestExceptionHandler<IRequest<BaseResponse>, BaseResponse, MyException>
    {
        protected override void Handle(IRequest<BaseResponse> request, MyException exception, RequestExceptionHandlerState<BaseResponse> state)
        {
            BaseResponse response = new BaseResponse();
            //Set some specific properties here in the response to indicate an error occurred
            state.SetHandled(response);
        }
    }
Run Code Online (Sandbox Code Playgroud)

rdv*_*ren 6

您可以像这样创建一个通用的:

public class ExceptionLoggingHandler<TRequest, TResponse, TException> : IRequestExceptionHandler<TRequest, TResponse, TException>
         where TRequest : IRequest<TResponse>
         where TException : Exception
    {
        private readonly ILogger<ExceptionLoggingHandler<TRequest, TResponse, TException>> _logger;

        public ExceptionLoggingHandler(ILogger<ExceptionLoggingHandler<TRequest, TResponse, TException>> logger)
        {
            _logger = logger;
        }

        public Task Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state, CancellationToken cancellationToken)
        {
            _logger.LogError(exception, "Something went wrong while handling request of type {@requestType}", typeof(TRequest));

            // TODO: when we want to show the user somethig went wrong, we need to expand this with something like
            // a ResponseBase where we wrap the actual response and return an indication whether the call was successful or not.
            state.SetHandled(default!);

            return Task.CompletedTask;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后在 IerviceC 上像这样注册它:

services.AddTransient(typeof(IRequestExceptionHandler<,,>), typeof(ExceptionLoggingHandler<,,>));
Run Code Online (Sandbox Code Playgroud)

因为该类RequestExceptionProcessorBehavior将寻找具有 3 个泛型的类型,而不是一个IRequestExceptionHandler<,>