告别重复检查!C#通用结果模式重构全解析

作者:微信公众号:【架构师老卢】
5-1 8:53
4

🔄 传统模式痛点:每个端点都要结果检查 假设我们有一个返回操作结果的接口:

app.MapGet("/", async () =>
{
    var result = await InvokeAsync();

    if(result.IsSuccess)
    {
        return TypedResults.BadRequest();
    }

    return TypedResults.Ok();
});

在每个端点中重复进行这种检查实在令人抓狂。


🛠️ 重构方案:通用结果模式

  1. 创建结果类型
public readonly struct Result<TValue, TError>
{
    private readonly TValue? _value;
    private readonly TError? _error;
    
    // 构造函数与属性定义...
    
    public static implicit operator Result<TValue, TError>(TValue value) => new(value);
    public static implicit operator Result<TValue, TError>(TError error) => new(error);
}

关键改进:通过隐式操作符简化类型转换:

// 优化前
return Result<Success, NotFound>.Failure(new NotFound());
// 优化后
return new NotFound();
  1. 实现错误处理器
public sealed class ErrorResult<TError>(TError error) : IResult
{
    public Task ExecuteAsync(HttpContext httpContext)
    {
        httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return httpContext.Response.WriteAsJsonAsync(error);
    }
}
  1. 终端结果封装
public sealed class EndpointResult<TValue, TError> : IResult
{
    private readonly IResult _result;
    
    public static implicit operator EndpointResult<TValue, TError>(Result<TValue, TError> result) 
        => result.IsSuccess 
            ? new EndpointResult<TValue, TError>(TypedResults.Ok(result.Value))
            : new EndpointResult<TValue, TError>(new ErrorResult<TError>(result.Error));
}

🚀 使用效果对比 重构前代码

async Task<Result<Success, NotFound>> UpdateNoteAsync(Guid id, string value)
{
    var note = await _dbContext.Notext.FindAsync(id);

    if(note == null)
    {
        return Result<Success, NotFound>.Failure(new NotFound())
    }

    note.Value = value;
    await _dbContext.SaveChangesAsync();
    return Result<Success, Error>.Success(new Success())
}

重构后代码

async Task<EndpointResult<Success, Error>> InvokeAsync()
{
    return await InternalInvokeAsync();
}

核心收益:
✅ 完全消除结果状态检查
✅ 代码量减少60%
✅ 统一错误处理流程


🧩 方案优势解析 | 特性 | 传统方案 | 新方案 | |---------------------|--------------------------|---------------------------| | 错误处理 | 每个端点重复检查 | 自动转换 | | 类型安全 | 需显式类型声明 | 隐式类型转换 | | 代码可维护性 | 高耦合 | 解耦业务与HTTP响应 | | 扩展性 | 修改需全局调整 | 新增错误类型即生效 |


🔧 实战应用场景

  1. Web API开发:直接返回业务逻辑结果
  2. 微服务通信:统一错误编码规范
  3. 领域驱动设计:保持领域模型纯净

🛠️ 进阶扩展建议

// 扩展自定义HTTP状态码
public sealed class CustomErrorResult<TError>(TError error, HttpStatusCode code) : IResult
{
    public Task ExecuteAsync(HttpContext context)
    {
        context.Response.StatusCode = (int)code;
        return context.Response.WriteAsJsonAsync(error);
    }
}

// 使用示例
return new CustomErrorResult<ErrorType>(error, HttpStatusCode.NotFound);

技术思考:
这个方案本质上是通过语言特性与类型系统的结合,将横切关注点(结果处理)转化为编译期约束。当隐式转换遇上结果模式,我们不仅消除了模板代码,更构建了具有自描述性的领域语言——这正是现代C#的演化方向。

相关留言评论
昵称:
邮箱:
阅读排行