如何实现支持泛型与函数参数的通用异步调用方法?
问题描述
现有代码结构
抽象参数基类及其子类
public abstract class BaseArgs { public abstract int CustomerID { get; set; } } public class InvoicesArgs : BaseArgs { public override int CustomerID { get; set; } } public class ContactsArgs : BaseArgs { public override int CustomerID { get; set; } }
抽象结果基类及其子类
public abstract class BaseResult { public abstract int RecordCount { get; set; } public abstract Exception Exception { get; set; } } public class InvoicesResult : BaseResult { public override int RecordCount { get; set; } public override Exception Exception { get; set; } } public class ContactsResult : BaseResult { public override int RecordCount { get; set; } public override Exception Exception { get; set; } }
业务方法
public InvoicesResult GetInvoices(InvoicesArgs args) { InvoicesResult result = new InvoicesResult() { RecordCount = 100 }; return result; } public ContactsResult GetContacts(ContactsArgs args) { ContactsResult result = new ContactsResult() { RecordCount = 55 }; return result; }
预期需求
希望实现一个通用异步方法Run,能接收上述业务方法作为参数,传入对应Args实例后返回对应Result实例,预期调用方式:
public class Test { public async void Run() { InvoicesResult invoicesResult = await Run<InvoicesResult>(GetInvoices, new InvoicesArgs() { CustomerID = 1 }); ContactsResult contactsResult = await Run<ContactsResult>(GetContacts, new ContactsArgs() { CustomerID = 1 }); } }
当前错误的Run方法
public async static Task<T> Run<T>(Action<BaseArgs> function, BaseArgs args) where T : new() { T result = new T(); await Task.Run(() => { try { result = function(args); } catch (Exception ex) { result.Exception = ex; }; }); return result; }
正确实现方案
当前代码存在三个核心问题:委托类型不匹配、泛型约束不足、类型转换逻辑错误,以下是修正后的实现:
public static async Task<TResult> Run<TArgs, TResult>(Func<TArgs, TResult> function, TArgs args) where TArgs : BaseArgs where TResult : BaseResult, new() { TResult result = new TResult(); try { // 异步执行业务方法,编译器自动匹配参数与返回值类型 result = await Task.Run(() => function(args)); } catch (Exception ex) { result.Exception = ex; } return result; }
优化后的调用方式
编译器可自动推导泛型参数,不需要手动指定,同时建议将async void改为async Task(异步编程最佳实践,避免异常无法捕获、无法等待等问题):
public class Test { public async Task Run() { var invoicesResult = await Run(GetInvoices, new InvoicesArgs() { CustomerID = 1 }); var contactsResult = await Run(GetContacts, new ContactsArgs() { CustomerID = 1 }); } }
关键改进说明
- 使用
Func<TArgs, TResult>委托,精准匹配业务方法的输入(TArgs)和输出(TResult)类型,替代原错误的Action<BaseArgs> - 添加泛型约束:限制
TArgs继承自BaseArgs,TResult继承自BaseResult且具备默认构造函数,确保类型安全 - 移除无效的类型转换逻辑,依赖编译器自动推导泛型参数,避免类型不兼容问题
- 修正异步方法的返回类型,遵循异步编程规范
内容的提问来源于stack exchange,提问作者MojoDK
相关产品推荐
相关产品推荐

