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

如何实现支持泛型与函数参数的通用异步调用方法?

问题描述

现有代码结构

抽象参数基类及其子类

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 06:43:02