未知泛型时如何将对象转换为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
相关产品推荐
相关产品推荐

