C# .NET如何实现可携带业务信息的自定义awaitable Task类
实现方案
核心思路
基于原生Task做轻量封装,无需重写复杂的可等待类型逻辑,即可满足你期望的调用方式:await后直接获取业务结果,同时可直接访问ServiceTask实例上的业务状态属性。
第一步:定义泛型ServiceTask类
public class ServiceTask<T> { // 内部承载原生Task执行逻辑 public Task<T> InnerTask { get; } public bool Success { get; internal set; } public string ErrorMessage { get; internal set; } = string.Empty; // 实现可等待模式要求的GetAwaiter方法,直接转发原生Task的Awaiter public TaskAwaiter<T> GetAwaiter() => InnerTask.GetAwaiter(); internal ServiceTask(Task<T> innerTask) { InnerTask = innerTask; } // 成功场景构造方法 public static ServiceTask<T> FromResult(T result) { return new ServiceTask<T>(Task.FromResult(result)) { Success = true }; } // 业务失败场景构造方法,直接解决你无法设置业务属性的问题 public static ServiceTask<T> FromError(string errorMsg, T? defaultResult = default) { return new ServiceTask<T>(Task.FromResult(defaultResult)) { Success = false, ErrorMessage = errorMsg }; } // 适配包含IO操作的异步逻辑构造 public static async ServiceTask<T> FromAsync(Func<Task<T>> func, CancellationToken token = default) { token.ThrowIfCancellationRequested(); try { var result = await func(); return FromResult(result); } catch (OperationCanceledException) { throw; // 取消操作按原生逻辑抛出 } catch (Exception ex) { // 程序异常可按需求选择抛出或走业务错误通路 return FromError(ex.Message); } } }
第二步:调整仓储方法实现
完全不需要限制泛型参数为ServiceResponse子类,业务状态和返回结果完全解耦:
public ServiceTask<IEnumerable<Account>?> GetAccountsAsync(Filter filter, CancellationToken token) { // 模拟带过滤条件的数据库查询 var accounts = DbContext.Accounts.Where(filter?.Expression ?? x => true).ToList(); if(accounts.Any()) { return ServiceTask<IEnumerable<Account>>.FromResult(accounts); } else if(filter != null) { return ServiceTask<IEnumerable<Account>>.FromError("Filter has restricted all Accounts"); } else { return ServiceTask<IEnumerable<Account>>.FromError("Database doesn't contain any Accounts"); } }
第三步:调用方式完全符合你的预期
var t = AccountResposistory.GetAccountsAsync(filter, token); var results = await t; if(t.Success) { return Results.Ok(results); } else { return Results.Problem(t.ErrorMessage); }
问题针对性说明
- 你提到的无法给ServiceTask设置业务属性的问题:通过静态构造方法
FromError/FromResult在实例返回前直接完成属性赋值,无需手动操作实例 - 不需要限制泛型T为ServiceResponse子类:业务状态属性直接封装在ServiceTask本身,和返回的业务结果T完全解耦,支持返回任意类型的业务结果,无需额外套Response壳
额外扩展
如果需要无返回值的异步方法,可单独实现非泛型的ServiceTask类,逻辑和泛型版一致即可。
内容的提问来源于stack exchange,提问作者Tod
相关产品推荐
相关产品推荐

