System.Reflection.Emit - 如果语句生成

时间:2015-12-31 00:27:26

标签: c# reflection compiler-construction clr il

我试图了解如何在C#中使用ILGenerator生成If语句。

这是我的代码:(ilg是ILGenerator)

ilg.Emit(OpCodes.Ldc_I4_1);
Label start = ilg.DefineLabel();
ilg.Emit(OpCodes.Brfalse, start);
ilg.Emit(OpCodes.Ldstr, "Hello");
ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
ilg.MarkLabel(start);

一些注意事项:

  • 独自调用Console.WriteLine完美运行。
  • 这是我运行生成的exe时遇到的错误:
  

未处理的异常:System.InvalidProgramException:公共语言运行时检测到无效的程序。在Testing.Test.Main(String [])

1 个答案:

答案 0 :(得分:4)

你的代码工作得很好,你只是忘了把public static void Main(string[] args) { var dynamicMethod = new DynamicMethod("PrintHello", typeof(void), null); var ilGenerator = dynamicMethod.GetILGenerator(); ilGenerator.Emit(OpCodes.Ldc_I4_1); var toEnd = ilGenerator.DefineLabel(); ilGenerator.Emit(OpCodes.Brfalse, toEnd); ilGenerator.Emit(OpCodes.Ldstr, "Hello"); ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); ilGenerator.MarkLabel(toEnd); ilGenerator.Emit(OpCodes.Ret); var @delegate = (Action)dynamicMethod.CreateDelegate(typeof(Action)); @delegate(); } 放到最后,看看有效的代码:

ilGenerator.Emit(OpCodes.Ret);

然后你会有这个输出

  

您好

如果您对此行System.InvalidProgramException发表评论,您将收到此异常

  

public static void Main(string[] args) { } :公共语言运行时检测到无效程序。

请记住,C#中的每个方法都必须包含 OpCode.Ret

如果你的Main方法是空的,就像这样

.method public hidebysig static void Main (string[] args) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 2 (0x2)
    .maxstack 8
    .entrypoint

    IL_0000: nop
    IL_0001: ret
} // end of method Program::Main

生成的IL(在调试模式下,没有优化)将是

.method public hidebysig static void Main (string[] args) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 1 (0x1)
    .maxstack 8
    .entrypoint

    IL_0000: ret
} // end of method Program::Main

IL生成(在发布模式下, 优化)将是

{{1}}