.NET 4.5 MethodBuilder.SetMethodBody - PullRequest
       16

.NET 4.5 MethodBuilder.SetMethodBody

5 голосов
/ 10 марта 2012

В новейшей версии .NET Framework, версия 4.5, класс MethodBuilder имеет метод с именем SetMethodBody, который, как я считаю, является именно той, на которую я смотрю как альтернатива использованию ILGenerator (что раздражает и ограничено в странные пути). Документацию можно найти здесь , хотя, поскольку .NET 4.5 еще не выпущен, он не полностью задокументирован. Я могу предоставить все аргументы, кроме двух, но в остальном мне понадобится помощь.

Первое, что я не понимаю, это byte[] localSignature, третий аргумент. MSDN заявляет, что это «Массив байтов, который содержит сериализованную структуру локальной переменной. Укажите ноль, если метод не имеет локальных переменных». Проблема в том, что это все, что я могу сказать, и я не могу найти формат «сериализованной подписи локальной переменной». Я попытался посмотреть в спецификации ECMA-335, но все, что я нашел, это как указать локальные переменные в разобранном CIL. Если бы кто-нибудь мог помочь мне понять это, это было бы очень ценно.

Кроме того, последний аргумент - IEnumerable<int> tokenFixups, который представляет собой «Набор значений, представляющих смещения в il, каждое из которых указывает начало токена, который может быть изменен. Укажите значение null, если у метода нет токенов, которые имеют быть измененным. " Я подозреваю, что мне не нужно их использовать, но я бы все равно хотел знать, что они собой представляют.

Спасибо, Brandon

1 Ответ

4 голосов
/ 19 марта 2012

Реальный ответ на мой вопрос был опубликован в виде комментария, а не ответа, так что в случае, если у кого-либо еще есть этот вопрос ... вот опубликованный ответ:

Вам понадобится класс SignatureHelper. Исправления предназначены только для компиляторов, которые переводят собственный код в IL, например, C ++ / CLI. - Ганс Пассант 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();

И чтобы установить тело метода в MethodBuilder, вы вызываете

MethodBuilder.SetMethodBody(il, maxStack, sigArray, handlers, fixups);

... где il - это byte[] с действительными инструкциями IL (см. на этой странице ), maxStack - целое число с количеством мест, резервируемых в стеке для метода, обработчики - это System.Reflection.Emit.ExceptionHandler[], а fixups - это массив int[], который можно игнорировать (с одним исключением, см. Ниже.)

В комментарии Ханса Пассанта я не согласен с тем, что исправления предназначены не только для компиляторов, которые переводят нативный код в IL. Работая над этим, я обнаружил, что если вы попытаетесь вызвать метод MethodBuilder, он выдаст неверную инструкцию. Глядя на ILGenerator в .NET рефлекторе, я обнаружил, что они генерируют исправления каждый раз, когда они вызывают вызов метода. Добавление исправления для каждого вызова метода действительно решило эту проблему. Могут быть и другие места, где вам нужно создать исправление, чтобы оно работало корректно, но я не особо разбирался в этом.

...