.NET 4.5 MethodBuilder.SetMethodBody

abo*_*u00 5 .net cil specifications .net-4.5

在最新版本的.NET框架4.5版本中,MethodBuilder类有一个调用的方法SetMethodBody,我相信这正是我所看到的作为使用ILGenerator的替代方法(这种方法很烦人,而且很奇怪).文档可以在这里找到,虽然因为.NET 4.5还没有出来,所以没有完全记录.我可以提供除了两个参数之外的所有参数,但其余的我需要帮助.

我不明白的第一个是byte[] localSignature第三个论点.MSDN声明它是"包含序列化局部变量结构的字节数组.如果方法没有局部变量,则指定null." 麻烦的是,就是这样,我无法找到"序列化局部变量签名"的格式.我试过查看ECMA-335规范,但我发现的是如何在未组装的CIL中指定局部变量.如果有人能帮我解决这个问题,我将不胜感激.

此外,最后一个参数是IEnumerable<int> tokenFixups,"表示il中偏移的值的集合,每个值指定可以修改的标记的开头.如果方法没有必须修改的标记,则指定null.".我怀疑我不需要使用这些,但我想知道它们是什么.

谢谢,布兰登

abo*_*u00 5

我的问题的真正答案是作为评论而不是答案发布的,所以如果其他人有这个问题......这是发布的答案:

您将需要 SignatureHelper 类。修正仅适用于将本机代码转换为 IL 的编译器,如 C++/CLI。– Hans Passant 3 月 10 日 13:02

所以...为了获取本地签名的字节数组,您可以执行以下代码:

var sig = SignatureHelper.GetLocalVarSigHelper(this.module);
sig.AddArgument(typeof(int)); //Local #0 is of type int
...
sig.AddArgument(typeof(string)); //Local #n is of type string
var sigArray = sig.GetSignature();
Run Code Online (Sandbox Code Playgroud)

为了在 MethodBuilder 上设置方法主体,您调用

MethodBuilder.SetMethodBody(il, maxStack, sigArray, handlers, fixups);
Run Code Online (Sandbox Code Playgroud)

...其中 il 是byte[]具有有效 IL 指令的一个(请参阅此页),maxStack 是一个整数,其中包含要在堆栈上为该方法保留的点数,handlers 是一个System.Reflection.Emit.ExceptionHandler[],而 fixups 是一个int[]可以忽略的数组(使用一个例外,见下文。)

在 Hans Passant 的评论中,我不同意的一件事是,修复不仅适用于将本机代码转换为 IL 的编译器。我在处理此问题时发现,如果您尝试发出对MethodBuilder方法的调用,它会发出错误的指令。查看 .NET 反射器中的 ILGenerator,我发现它们每次发出方法调用时都会发出一个修正。为每个方法调用添加一个修正确实解决了这个问题。可能还有其他地方您需要发出修正才能使其正常工作,但我并没有深入研究。