You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Clean Architecture架构异常处理方案与错误码归属咨询

方案可行性验证与实践建议

一、MediatR装饰器处理领域层异常的落地思路

你的方案完全符合Clean Architecture的依赖规则,核心实现可以通过MediatR管道行为完成:

  • 实现IPipelineBehavior<TRequest, TResult>通用管道,其中TResult约束为Fluent Results的Result类型,在Handle方法中捕获领域层的两类异常,转换为Result.Fail()格式
  • 该管道属于应用层组件,不侵入领域层,完美规避了在领域层引入Fluent Results的问题
  • 示例代码:
public class DomainExceptionPipeline<TRequest, TResult> : IPipelineBehavior<TRequest, TResult>
    where TResult : Result, new()
{
    public async Task<TResult> Handle(TRequest request, RequestHandlerDelegate<TResult> next, CancellationToken cancellationToken)
    {
        try
        {
            return await next();
        }
        catch (BusinessRuleValidationException ex)
        {
            return new TResult().WithError(ex.Message) as TResult;
        }
        catch (NullReferenceException ex)
        {
            // 建议把空引用异常转化为明确的业务提示,避免暴露底层细节
            return new TResult().WithError("请求的资源不存在或参数无效") as TResult;
        }
    }
}
  • 额外建议:领域层尽量避免抛出NullReferenceException,可以通过提前空值检查抛出BusinessRuleValidationException,统一业务异常类型,减少后续处理分支。

二、基础设施层改用Fluent Results的核心原则

  • 基础设施层(仓储、外部服务集成等)所有操作直接返回Result/Result<T>,不再抛出异常,所有错误封装为Fluent Results的Error对象
  • 错误信息需包含技术细节(如数据库连接超时、第三方服务返回错误码),但不要关联HTTP状态码——基础设施层属于底层实现,可能被API、后台任务、控制台程序等多种上层组件调用,硬编码HTTP状态码会导致严重耦合,违反单一职责原则。
关于HTTP状态码的决策方案
  • 禁止基础设施层返回HTTP状态码:底层组件不应该依赖上层API的协议细节,否则后续扩展其他调用场景时会面临大量代码改造
  • 由API层统一决定HTTP状态码:
    1. 在基础设施层返回Error时,通过WithMetadata附加错误类型标识(比如ErrorType.InfrastructureFailure、ErrorType.DataNotFound)
    2. API层实现统一的结果处理逻辑,根据Result中的错误类型映射对应的HTTP状态码:
      • 领域层业务规则校验失败 → 400 Bad Request
      • 基础设施层故障(如数据库连接失败) → 500 Internal Server Error
      • 资源不存在 → 404 Not Found
    3. 示例处理逻辑:
public class BaseApiController : ControllerBase
{
    protected IActionResult MapResultToResponse(Result result)
    {
        if (result.IsSuccess)
            return Ok(result.Value);

        var firstError = result.Errors.First();
        if (firstError.Metadata.TryGetValue("ErrorType", out var errorTypeObj) &&
            errorTypeObj is ErrorType errorType)
        {
            return errorType switch
            {
                ErrorType.BusinessRuleViolation => BadRequest(result.Errors.Select(e => e.Message)),
                ErrorType.InfrastructureFailure => StatusCode(500, "服务内部异常,请稍后重试"),
                ErrorType.NotFound => NotFound(result.Errors.Select(e => e.Message)),
                _ => BadRequest("请求参数无效")
            };
        }

        return BadRequest("请求处理失败");
    }
}
额外优化点
  • 强制所有MediatR Handler的返回类型统一为Result/Result<T>,避免混合返回值与异常的情况
  • 可以给Fluent Results的Error扩展自定义方法,快速添加错误类型元数据,简化基础设施层的错误封装代码

内容的提问来源于stack exchange,提问作者PelikanFix16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 08:45:37