LightResults:简洁高效的结果模式实践
项目介绍
LightResults 是一个轻量级、现代化的 .NET 库,它提供了一种简单且灵活的结果模式(Result Pattern)实现。结果模式是一种表示操作结果(无论是成功还是遇到错误)的更明确、更结构化的方法。本项目受到 Michael Altmann 的 FluentResults 项目的启发。
项目技术分析
LightResults 旨在帮助开发者更好地处理操作结果,通过将成功或失败的结果封装在易于使用的对象中,增强了代码的可读性和可维护性。以下是该项目的一些技术亮点:
- 轻量级:LightResults 仅包含实现结果模式所必需的组件。
- 可扩展:简单的接口和基类使得库易于适配和扩展。
- 不可变:结果和错误对象一旦创建就无法更改,保证了对象的不可变性。
- 线程安全:错误列表和元数据字典使用不可变类,确保线程安全。
- 现代化:基于最新版本的 .NET 开发,采用最新的最佳实践。
- 本地化:在最新版本的 .NET 环境下编写、编译和测试。
- 兼容性:作为 .NET Standard 2.0 库提供,支持数十种 .NET 版本。
- 可修剪:从 .NET 7.0 开始,支持预先编译(AOT)。
- 高性能:经过优化和基准测试,以实现最佳性能。
项目技术应用场景
LightResults 适用于任何需要明确表示操作结果的场景。以下是一些典型的使用场景:
- API 调用:在 Web API 中,返回 LightResults 结果对象而不是直接抛出异常,可以提供更丰富的错误信息。
- 业务逻辑:在业务逻辑中,使用 LightResults 可以更容易地处理复杂操作的中间结果。
- 数据验证:在对输入数据进行验证时,可以收集并返回所有错误,而不是在发现第一个错误时就停止。
项目特点
以下是 LightResults 的一些显著特点:
简单的类结构
LightResults 主要由三个类组成:Result
、Result<TValue>
和 Error
。
Result
类表示一个通用的结果,指示成功或失败。Result<TValue>
类表示一个带有值的结果。Error
类表示一个错误,包含消息和关联的元数据。
创建成功和失败的结果
成功结果可以通过 Ok
方法创建,失败结果可以通过 Fail
方法创建。
var successResult = Result.Ok();
var successResultWithValue = Result.Ok(349.4);
var failedResult = Result.Fail();
var failedResultWithMessage = Result.Fail("操作失败!");
var failedResultWithMessageAndMetadata = Result.Fail("操作失败!", ("异常", ex));
检查结果状态
结果具有 IsSuccess
和 IsFailed
两个属性,它们是互斥的。
if (result.IsSuccess)
{
// 结果成功,因此 IsFailed 将为 false。
}
if (result.IsFailed)
{
// 结果失败,因此 IsSuccess 将为 false。
if (result.Error.Message.Length > 0)
Console.WriteLine(result.Error.Message);
else
Console.WriteLine("发生未知错误!");
}
获取值
从成功结果中获取值可以通过 Value
属性进行。
if (result.IsSuccess)
{
var value = result.Value;
}
创建错误
错误可以带消息或不带消息创建。
var errorWithoutMessage = new Error();
var errorWithMessage = new Error("出错了!");
还可以带元数据创建。
var errorWithMetadataTuple = new Error(("键", "值"));
var metadata = new Dictionary<string, object> { { "键", "值" } };
var errorWithMetadataDictionary = new Error(metadata);
或者,带消息和元数据创建。
var errorWithMetadataTuple = new Error("出错了!", ("键", "值"));
var errorWithMetadataDictionary = new Error("出错了!", metadata);
自定义错误
为了表示特定的错误,可以创建继承自 Error
的自定义错误类。
public sealed class 资源未找到错误 : Error
{
public 资源未找到错误()
: base("资源无法找到。")
{
}
}
var notFoundError = new 资源未找到错误();
var notFoundResult = Result.Fail(notFoundError);
然后可以根据错误类型检查结果。
if (result.IsFailed && result.HasError<资源未找到错误>())
{
// 看起来资源未找到,我们得采取一些措施!
}
结合元数据使用时,这可以特别有用,以处理异常。
public sealed class 未处理的异常错误 : Error
{
public 未处理的异常错误(Exception ex)
: base("发生未处理的异常。", ("异常", ex))
{
}
}
这样我们可以在代码中使用 try-catch 块,但返回结果而不是抛出异常。
public Result DoSomeWork()
{
try
{
// 在这个方法中我们绝对不能抛出异常!
}
catch(Exception ex)
{
var unhandledExceptionError = new 未处理的异常错误(ex);
return Result.Fail(unhandledExceptionError);
}
return Result.Ok();
}
通过创建错误工厂,可以进一步简化错误创建过程。
public static AppError
{
public Result NotFound()
{
var notFoundError = new 资源未找到错误();
return Result.Fail(notFoundError);
}
public Result UnhandledException(Exception ex)
{
var unhandledExceptionError = new 未处理的异常错误(ex);
return Result.Fail(unhandledExceptionError);
}
}
这样就能更清晰、更明确地描述结果。
public Result GetPerson(int id)
{
var person = _database.GetPerson(id);
if (person is null)
return AppError.NotFound();
return Result.Ok();
}
LightResults 以其简单性和易用性,为 .NET 开发者提供了一个强大的工具,以更好地处理和表示操作结果。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考