Как использовать условное в Reflection.Emit - PullRequest
0 голосов
/ 27 сентября 2018

Здравствуйте, я генерирую класс, используя Reflection.Emit, и я хочу знать, как вы используете команду 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 при будущих казнях?

PS После получения исчерпывающих ответов это моя версия:

        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);

1 Ответ

0 голосов
/ 27 сентября 2018

Вам никогда не придется иметь дело с адресами кода явно.Для того, чтобы прыгать, вам нужно определить метки:

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);
...