如何在 Reflection.Emit 中使用条件
How to use conditional in Reflection.Emit
您好,我正在使用 Reflection.Emit
生成 class,我想知道您如何使用 brfalse
命令来实现 conditionals
。
具体来说,我不知道如何将 IL 转换为 OPCODES brfalse.s 命令。
我的方法具有以下形式:
object MyMethod()
{
if(isTransaction) //isTransaction is a bool property
return Method1();
else return 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);
您好,我正在使用 Reflection.Emit
生成 class,我想知道您如何使用 brfalse
命令来实现 conditionals
。
具体来说,我不知道如何将 IL 转换为 OPCODES brfalse.s 命令。
我的方法具有以下形式:
object MyMethod()
{
if(isTransaction) //isTransaction is a bool property
return Method1();
else return 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);