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

如何在PostFixPatchFactory中通过IL Emit实现补丁方法执行次数统计?

实现PostFix补丁执行次数统计方案

核心思路

给动态生成的补丁类型添加实例字段存储执行次数,在PostFix方法的IL开头插入自增逻辑,同时可通过接口封装属性方便外部访问。

步骤1:在动态类型中定义实例字段

在创建动态类型(TypeBuilder)的代码中,添加一个公开的int类型实例字段:

// 假设typeBuilder是你创建的动态类型构建器
var timesExecutedField = typeBuilder.DefineField(
    "TimesExecuted",
    typeof(int),
    FieldAttributes.Public | FieldAttributes.Instance);

步骤2:在PostFix方法IL中插入计数逻辑

在生成PostFix方法的ILGenerator代码最开头,添加字段自增的IL指令:

// 获取PostFix方法的IL生成器
var il = postFixMethodBuilder.GetILGenerator();

// 插入计数自增逻辑(必须放在原有业务逻辑之前)
// 1. 加载当前实例(this)到栈顶
il.Emit(OpCodes.Ldarg_0);
// 2. 取出当前TimesExecuted字段的值
il.Emit(OpCodes.Ldfld, timesExecutedField);
// 3. 加载常数1
il.Emit(OpCodes.Ldc_I4_1);
// 4. 执行加法(字段值 + 1)
il.Emit(OpCodes.Add);
// 5. 将计算结果存回TimesExecuted字段
il.Emit(OpCodes.Stfld, timesExecutedField);

// 以下是你原来的PostFix方法IL逻辑(比如处理参数、调用原方法等)
// ... 原有IL代码 ...

步骤3:通过接口简化访问(可选)

如果希望更优雅地访问计数,可定义一个接口并让动态类型实现它:

// 定义公共接口
public interface IPatchExecutionCounter
{
    int TimesExecuted { get; }
}

然后在动态类型构建时添加接口实现,并生成属性的get方法:

// 让动态类型实现接口
typeBuilder.AddInterfaceImplementation(typeof(IPatchExecutionCounter));

// 构建TimesExecuted属性
var propertyBuilder = typeBuilder.DefineProperty(
    "TimesExecuted",
    PropertyAttributes.None,
    typeof(int),
    null);

// 生成属性的get方法
var getMethod = typeBuilder.DefineMethod(
    "get_TimesExecuted",
    MethodAttributes.Public | MethodAttributes.Virtual,
    typeof(int),
    Type.EmptyTypes);
var getIl = getMethod.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, timesExecutedField);
getIl.Emit(OpCodes.Ret);

// 绑定属性的get方法
propertyBuilder.SetGetMethod(getMethod);

之后创建补丁实例时,直接强转接口即可访问:

var patchInstance = Activator.CreateInstance(dynamicPatchType) as IPatchExecutionCounter;
// 访问执行次数
Console.WriteLine($"补丁已执行:{patchInstance.TimesExecuted} 次");

关键注意事项

  • 确保PostFix方法是实例方法:因为要访问实例字段,所以创建MethodBuilder时不要加MethodAttributes.Static
  • 参数索引正确性:实例方法的第一个参数(Ldarg_0)是当前实例,原有补丁的参数(如__instance、__result)会从Ldarg_1开始,需调整原有IL代码中的参数索引
  • IL指令顺序:计数逻辑必须放在原有业务逻辑之前,确保每次执行都能正确累加

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:22:44