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

未知泛型时如何将对象转换为Func<In,Out>并实现通用异步任务处理

问题描述

我有大量接收Request类并返回Response类的函数,想要编写一个通用处理器。限制条件:无法修改JobParametersModel类的定义使其支持泛型,也不能修改DoWorkAsync方法,但可以修改其他所有内容。

现有类定义:

public class JobRequestModel<Request, Response>
    where Request : class
    where Response : class
{
    public Func<Request, Task<Response>> CallDelegate { get; set; }

    public async Task<Response> DoCall(Request request)
    {
        return await CallDelegate(request);
    }
}

public sealed class JobParametersModel
{
    // 存储JobRequestModel和其他参数
    public object RequestModel { get; set; }
}

我卡在DoWorkAsync方法的实现上:如何把work.RequestModel这个object转换为可调用的类型?以下是我尝试但无法运行的代码:

// 无法运行的尝试代码
public async Task<JobResultModel> DoWorkAsync(JobParametersModel work, object request)
{
    var jobRequestModel = (JobRequestModel)work.RequestModel; // 编译不通过,JobRequestModel是泛型类
    
    // 可通过ChangeType转换request,此处简化示例
    var results = await jobRequestModel.DoCall(request);
    
    // 后续打包/返回结果
}

期望的调用方式:

var result1 = await DoWorkAsync(
    new JobParametersModel()
    {
        RequestModel = new JobRequestModel<CustomRequestType, CustomResponseType>()
        {
            CallDelegate = _client.getMyCustomDelegate
        }
    },
    new CustomRequestType()
    {
        CustomField1 = "something",
        CustomField2 = 4
    }
);

var result2 = await DoWorkAsync(
    new JobParametersModel()
    {
        RequestModel = new JobRequestModel<OtherCustomRequestType, OtherCustomResponseType>()
        {
            CallDelegate = _client.getSomeOtherCustomDelegate
        }
    },
    new OtherCustomRequestType()
    {
        DifferentField1 = "other things"
    }
);

解决方案1:定义非泛型接口(推荐)

通过给泛型类添加非泛型接口,实现类型统一调用,兼顾类型安全与性能。

步骤1:定义非泛型接口

public interface IJobRequestModel
{
    Task<object> DoCallAsync(object request);
}

步骤2:让泛型类实现接口

修改JobRequestModel<Request, Response>,显式实现接口方法:

public class JobRequestModel<Request, Response> : IJobRequestModel
    where Request : class
    where Response : class
{
    public Func<Request, Task<Response>> CallDelegate { get; set; }

    public async Task<Response> DoCall(Request request)
    {
        return await CallDelegate(request);
    }

    // 显式实现非泛型接口方法
    async Task<object> IJobRequestModel.DoCallAsync(object request)
    {
        if (request is not Request typedRequest)
            throw new ArgumentException($"请求类型不匹配,预期类型:{typeof(Request).FullName}", nameof(request));
        
        var response = await DoCall(typedRequest);
        return response;
    }
}

步骤3:修改DoWorkAsync方法

通过非泛型接口完成调用:

public async Task<JobResultModel> DoWorkAsync(JobParametersModel work, object request)
{
    if (work.RequestModel is not IJobRequestModel jobRequestModel)
        throw new InvalidOperationException("RequestModel必须实现IJobRequestModel接口");
    
    var resultObj = await jobRequestModel.DoCallAsync(request);
    
    // 根据实际需求将resultObj打包为JobResultModel
    return new JobResultModel
    {
        // 填充对应属性,例如 Result = resultObj
    };
}

解决方案2:使用反射(备选,不推荐)

如果不想修改JobRequestModel,可以用反射调用方法,但性能较差且无类型检查,容易出错。

public async Task<JobResultModel> DoWorkAsync(JobParametersModel work, object request)
{
    var requestModelType = work.RequestModel.GetType();
    // 获取泛型类的DoCall方法
    var doCallMethod = requestModelType.GetMethod(nameof(JobRequestModel<object, object>.DoCall));
    if (doCallMethod == null)
        throw new InvalidOperationException("找不到DoCall方法");
    
    // 调用方法并等待执行完成
    var task = (Task)doCallMethod.Invoke(work.RequestModel, new[] { request });
    await task;
    
    // 获取返回结果
    var resultObj = task.GetType().GetProperty("Result")?.GetValue(task);
    
    // 打包为JobResultModel返回
    return new JobResultModel
    {
        // 填充对应属性
    };
}

注意事项

  • 接口方案类型安全、性能优异,优先选择。
  • 若需要处理请求类型转换,可在接口方法中添加Convert.ChangeType逻辑,确保request能转为对应泛型Request类型。

内容的提问来源于stack exchange,提问作者William YK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:01:02