如何在运行时删除 Emit IL 的最后几段

How to remove the last few segments of Emit IL at runtime

如何在运行时删除 Emit IL 的最后几段

我试图修改几千行代码中的一些逻辑,我想使用回滚 IL 的方式添加新逻辑,避免更改以前的代码。

简单例如:

希望去掉Emit IL的最后几段,然后在isSomeLogic为真时发出新的il。

void Main()
{
    DynamicMethod methodbuilder = new DynamicMethod("Deserialize" + Guid.NewGuid().ToString(), typeof(void), null);
    var il = methodbuilder.GetILGenerator();
    il.Emit(OpCodes.Ldstr, "Hello World");
    Type[] types = new Type[1]{typeof(string)};
    MethodInfo method = typeof(Console).GetMethod("WriteLine", types);
    il.Emit(OpCodes.Call, method);
    il.Emit(OpCodes.Ret);

    // do some thing...
    var isSomeLogic = true;
    if( isSomeLogic ){
        //remove the il OpCodes.Ret and add new logic Emit
        il.Emit(OpCodes.Ret);
    }

    var func = (Action)methodbuilder.CreateDelegate(typeof(Action));
    func();
}

ILGenerator 只是前锋。您不能删除 您添加的操作码。相反,只是......不添加它们?或者,您可以使用 Label 和跳转操作; Ret 不需要位于方法的 end 处;以下是完全有效的,只要堆栈在 ret 处的高度正确,并且堆栈高度对于到特定位置的所有路径都是相同的。

  • 做事
  • 跳转到 X
  • 标签:Y
  • 做更多事情
  • ret
  • 标签:X
  • 做更多的事情
  • 跳转到 Y