How to remove the last few segments of Emit IL at runtime
I tried to modify some logic in a thousand lines of code, I want to use the rollback IL way to add new logic, avoid changing the previous code.
I hope to remove the last few segments of Emit IL and then emit new il when isSomeLogic
is true.
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
is forwards only. You can't remove opcodes that you've added. Instead, just... don't add them? Alternatively, you can use Label
and jump operations; the Ret
doesn't need to be at the end of a method; the following is perfectly valid, as long as the stack is at the correct height at the ret, and the stack height is the same for all paths to a particular location.