namespace Dpz.Core.Service.Mediator.Common.Behaviors;

/// <summary>
/// Mediator 异常包装管道:统一捕获处理器异常并尝试转换为 ResponseResult。
/// </summary>
/// <typeparam name="TMessage">消息类型。</typeparam>
/// <typeparam name="TResponse">响应类型。</typeparam>
public sealed class MediatorExceptionWrappingBehavior<TMessage, TResponse>(
    ILogger<MediatorExceptionWrappingBehavior<TMessage, TResponse>> logger
) : IPipelineBehavior<TMessage, TResponse>
    where TMessage : IMessage
{
    /// <summary>
    /// 执行异常包装管道逻辑。
    /// </summary>
    public async ValueTask<TResponse> Handle(
        TMessage message,
        MessageHandlerDelegate<TMessage, TResponse> next,
        CancellationToken cancellationToken
    )
    {
        try
        {
            return await next(message, cancellationToken);
        }
        catch (Exception ex)
        {
            logger.LogError(
                ex,
                "[Mediator] Handler exception captured: {MessageName}",
                typeof(TMessage).Name
            );

            if (TryCreateFailResponse(ex, out var wrappedResponse))
            {
                return wrappedResponse;
            }

            throw;
        }
    }

    /// <summary>
    /// 尝试根据响应类型创建统一失败结果。
    /// </summary>
    private static bool TryCreateFailResponse(Exception ex, out TResponse response)
    {
        var responseType = typeof(TResponse);

        if (responseType == typeof(ResponseResult))
        {
            response = (TResponse)(object)ResponseResult.Fail(ex.Message, 500);
            return true;
        }

        if (
            responseType.IsGenericType
            && responseType.GetGenericTypeDefinition() == typeof(ResponseResult<>)
        )
        {
            var method = responseType.GetMethod("WithFail", [typeof(string), typeof(int)]);
            var instance = Activator.CreateInstance(responseType);

            if (method == null || instance == null)
            {
                response = default!;
                return false;
            }

            var value = method.Invoke(instance, [ex.Message, 500]);
            if (value is TResponse casted)
            {
                response = casted;
                return true;
            }

            if (instance is TResponse fallback)
            {
                response = fallback;
                return true;
            }
        }

        response = default!;
        return false;
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这是一个基于 MediatR 模式实现的异常包装管道行为(Pipeline Behavior)。让我详细解释一下这段代码:

代码概述

这是一个泛型类 MediatorExceptionWrappingBehavior,实现了 IPipelineBehavior 接口,用于在 Mediator 模式中统一处理异常并将其转换为标准化的响应格式。

主要功能

1. 异常捕获与处理

public async ValueTask<TResponse> Handle(...)
{
    try
    {
        return await next(message, cancellationToken);
    }
    catch (Exception ex)
    {
        // 记录异常日志
        logger.LogError(ex, "[Mediator] Handler exception captured: {MessageName}", typeof(TMessage).Name);
        
        // 尝试创建失败响应
        if (TryCreateFailResponse(ex, out var wrappedResponse))
        {
            return wrappedResponse;
        }
        
        // 如果无法创建失败响应,重新抛出异常
        throw;
    }
}

2. 智能响应转换

TryCreateFailResponse 方法通过反射机制智能判断响应类型并创建相应的失败响应:

处理 ResponseResult 类型

if (responseType == typeof(ResponseResult))
{
    response = (TResponse)(object)ResponseResult.Fail(ex.Message, 500);
    return true;
}

处理泛型 ResponseResult<T> 类型

if (responseType.IsGenericType && 
    responseType.GetGenericTypeDefinition() == typeof(ResponseResult<>))
{
    // 通过反射调用 WithFail 方法
    var method = responseType.GetMethod("WithFail", [typeof(string), typeof(int)]);
    var instance = Activator.CreateInstance(responseType);
    
    var value = method.Invoke(instance, [ex.Message, 500]);
    // 尝试转换并返回响应
}

设计优势

  1. 统一异常处理:在管道层面统一捕获和处理所有处理器异常
  2. 类型安全:通过泛型约束确保类型安全
  3. 灵活性:支持多种响应类型的自动转换
  4. 日志记录:自动记录异常信息便于调试
  5. 优雅降级:如果无法创建失败响应,会重新抛出原始异常

使用场景

这个管道行为通常在以下场景中使用:

  • Web API 中统一返回格式化的错误响应
  • 微服务间通信的错误处理
  • 需要将内部异常转换为用户友好错误消息的场景

依赖注入

通过构造函数注入 ILogger,支持结构化日志记录,便于监控和调试。

这是一个非常实用的管道行为实现,能够显著提高应用程序的错误处理一致性和用户体验。

评论加载中...