您好,我正在使用 Reflection.Emit
生成一个类,我想知道如何使用 brfalse
命令作为条件
。
具体来说,我不知道如何将brfalse.s命令的IL转换为OPCODES。
我的方法具有以下形式:
对象 MyMethod()
{
if(isTransaction)//isTransaction 是一个 bool 属性
返回方法1();
否则返回 Method2();
}
有条件
IL_0000: ldarg.0 // this
IL_0001: call instance bool RediusTests.DaemonBase::get_IsTransaction()
IL_0006: brfalse.s IL_0020 //how is this translated within opcodes?
第一个分支:
IL_0008:ldarg_0
IL_....... ///INSTRUCTIONS
IL_......
IL_001f:ret
第二个分支:
IL_0020:ldarg_0 //How do i specify with OPCODES to jump here?????
IL_.......
IL_......
IL_001f:ret
对于第一个片段,brfalse.s
的参数是什么?
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brfalse,); //what do i put here in the overload?
正如您在最后一个片段、最后一行中看到的,我应该在 ilgen.Emit
的重载中放入什么?什么都没有,20或者是否有其他代码可以转换为IL_0020
?
而且,每次运行程序时,指令的地址不是存储在不同的内存地址吗?在以后的执行中,它不会从 IL0020
更改为 IL00xx
?
P.S在收到一些全面的答案后,这是我迄今为止的版本:
ILGenerator ilgen = newMethod.GetILGenerator();
Label falseLabel = ilgen.DefineLabel();
Label continueLabel = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brtrue,continueLabel); //branching
ilgen.MarkLabel(continueLabel); //true branch
----instructions------
ilgen.Emit(OpCodes.Ret);
ilgen.Emit(OpCodes.Br,continueLabel);
ilgen.MarkLabel(falseLabel); //false branch
--instructions----
ilgen.Emit(OpCodes.Ret);
最佳答案
您永远不必显式处理代码地址。 为了跳转,需要定义标签:
Label falseLabel = ilgen.DefineLabel();
Label continueLabel = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Call, getIsTransaction);
ilgen.Emit(OpCodes.Brfalse, continueLabel);
// getIsTransaction returned true
...
ilgen.Emit(OpCodes.Br, continueLabel);
ilgen.MarkLabel(falseLabel);
// getIsTransaction returned false
...
ilgen.MarkLabel(continueLabel);
关于c# - 如何在 Reflection.Emit 中使用条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52531308/