基于Mono.Cecil如何调用Task.FromResult<bool>(true)生成对应IL代码
实现泛型方法调用的完整步骤
首先明确核心差异:非泛型方法直接通过ImportReference导入即可使用,而Mono.Cecil中调用泛型方法,必须额外对泛型方法做参数实例化,生成可直接落地的构造泛型方法引用,不能直接拿未绑定泛型参数的泛型定义来生成指令。
具体实现代码(直接替换你代码中的注释位置)
// 1. 通过反射获取Task.FromResult的泛型方法定义(该方法本身带1个泛型参数T) var fromResultGenericDef = typeof(Task).GetMethod( nameof(Task.FromResult), BindingFlags.Public | BindingFlags.Static ); // 2. 将泛型方法定义导入到当前编辑的程序集模块中,拿到未绑定泛型参数的原始方法引用 MethodReference rawMethodRef = module.ImportReference(fromResultGenericDef); // 3. 实例化泛型方法:将方法的泛形参数T绑定为bool类型 var constructedMethod = new GenericInstanceMethod(rawMethodRef); // 向构造方法的泛型参数列表中添加bool类型的模块引用 constructedMethod.GenericArguments.Add(module.ImportReference(typeof(bool))); // 4. 向指令流中插入对应的Call指令,此时生成的IL完全匹配目标要求 ins.Add(processor.Create(OpCodes.Call, constructedMethod));
关键避坑说明
- 不要混淆泛型承载主体:
Task.FromResult是定义在非泛型静态Task类上的泛型方法,不需要额外构造Task<T>的泛型类型实例,仅需要对方法本身的泛型参数做绑定即可。 - 不能直接使用导入后的原始方法引用生成指令:如果跳过
GenericInstanceMethod的实例化步骤,生成的IL会是未绑定泛型参数的泛型方法占位符,无法被运行时正确识别,和最终预期的IL输出不匹配。 - 所有类型引用必须关联当前编辑的模块:不管是泛型方法本身,还是绑定的泛型参数类型(比如这里的
bool),都需要通过当前模块的ImportReference方法做映射,不能直接使用反射的Type对象硬拼接元数据,否则会出现元数据解析错误。
最终生成的IL验证
按照上述代码生成的IL指令流,完全和目标要求等价:
// 对应你代码中已写好的指令 ldc.i4.1 // 对应插入的构造泛型方法调用指令 // 你参考的目标IL中出现的!!0是泛型方法定义的参数占位符,实例化后会替换为绑定的bool类型 call class [mscorlib]System.Threading.Tasks.Task`1<bool> [mscorlib]System.Threading.Tasks.Task::FromResult(bool) // 对应你代码中已写好的指令 ret
内容的提问来源于stack exchange,提问作者Just a learner
相关产品推荐
相关产品推荐

