如何通过字节形式的CIL代码直接添加或修改程序集的方法体?
可行解决方案
方案1:直接使用Mono.Cecil原生支持的原始字节写入能力
你对Mono.Cecil的原有认知存在偏差,它本身就支持直接将原始CIL字节数组写入方法体,不需要手动逐行构造IL指令,也不需要自行开发IL解析器。
具体操作逻辑如下:
- 获取目标方法的
MethodDefinition实例 - 调用
MethodBody.Create(MethodDefinition method, int codeSize)初始化方法体 - 直接将你持有的CIL字节数组赋值给方法体的
Code属性 - 按需修正方法体的
MaxStack、局部变量签名、异常处理表等元数据即可
示例代码片段:
// 假设你已经拿到目标方法的methodDef实例,以及原始IL字节数组ilBytes methodDef.Body = MethodBody.Create(methodDef, ilBytes.Length); Buffer.BlockCopy(ilBytes, 0, methodDef.Body.Code, 0, ilBytes.Length); // 按需设置MaxStack,不确定具体值时可先设置为8,大部分场景下可兼容 methodDef.Body.MaxStack = 8; // 如果IL用到了局部变量,同步更新LocalVariables集合 // 如果IL用到了异常处理,同步更新ExceptionHandlers集合
方案2:使用AsmResolver库
AsmResolver是另一款成熟的.NET程序集编辑库,对原始IL字节的写入支持更友好,无需额外处理底层结构:
- 它的
CilMethodBody类直接提供FromRawBytes静态方法,可以直接用CIL字节数组生成完整方法体 - 内置自动计算MaxStack、校验IL结构的能力,降低手动配置出错概率
示例代码片段:
using AsmResolver.DotNet; using AsmResolver.DotNet.Code.Cil; // 从字节数组生成方法体 var body = CilMethodBody.FromRawBytes(methodDef, ilBytes); methodDef.CilMethodBody = body;
注意事项
- 如果你持有的CIL字节数组包含元数据令牌引用(比如类型、方法、字符串的引用),需要确保令牌在目标程序集中的有效性,或者提前完成令牌重定向
- 调用完写入逻辑后直接保存程序集即可完成修改,不需要额外的IL解析步骤
内容的提问来源于stack exchange,提问作者Arthur Robert
相关产品推荐
相关产品推荐

