Определение настраиваемых атрибутов в CIL

Каков синтаксис определения литерала массива в CIL для украшения члена настраиваемым атрибутом?

Я пишу код .NET на CIL (используя ilasm.exe для его компиляции), и мне нужно украсить метод настраиваемым атрибутом. Конструктор этого атрибута принимает в качестве единственного параметра массив целых чисел. Как я могу сделать это в CIL?

Это подпись конструктора настраиваемого атрибута (я не могу ее изменить):

public FooAttribute(int[] values) {
// some hidden constructor stuff
}

Вот так я бы украсил свой метод, если бы писал на C # (но не могу):


[Foo(new int[] {1, 2, 3, 4})]
public string Bar() {
  return "Some text";
}

Использование ildasm.exe для просмотра скомпилированного C # (чтобы попытаться понять его с помощью обратного проектирования) дает мне уродливый и непригодный для использования двоичный литерал. Вместо этого я попытался использовать Reflector.NET, и он выглядит намного лучше, но ilasm.exe выдает синтаксическую ошибку при ключевом слове «новый», поэтому я не могу его использовать:

.custom instance void SomeNamespace.FooAttribute::.ctor(int32[]) = { new int32[int32(4)] { int32(1), int32(2), int32(3), int32(4) } }

person Jono    schedule 11.06.2010    source источник


Ответы (1)


Трудно догадаться, в чем может быть ваша проблема. Если я применяю этот атрибут к методу Program.Test (), я получаю следующее:

  .method private hidebysig static void  Test() cil managed
  {
    .custom instance void ConsoleApplication1.FooAttribute::.ctor(int32[]) = ( 01 00 04 00 00 00 01 00 00 00 02 00 00 00 03 00 
                                                                               00 00 04 00 00 00 00 00 ) 
    // Code size       2 (0x2)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ret
  } // end of method Program::Test

Запустите это через ilasm.exe, без проблем. Обратите внимание, как значения элементов массива (прокрутите окно фрагмента вправо, чтобы увидеть их) уже преобразованы в формат, необходимый для их внедрения в таблицу данных конструктора атрибутов. BitConverter.GetBytes () может частично выполнить эту работу. Документ Ecma должен иметь требуемый формат этих данных.

person Hans Passant    schedule 11.06.2010
comment
На выходе ildasm (как вы показали выше) массив уже преобразован в правильный формат, но это не требуется, и для других типов / аргументов их можно предоставить в формате: ‹code› = {строка ('Hello, World!') Bool (true) type (int32) type ([System.Xml] System.Xml.XmlDocument)} ‹/code› вместо предварительного форматирования. - person Jono; 11.06.2010
comment
Я не могу это прочитать. Ecma 335, раздел 2, глава 21 говорит, что вы не можете. Данные Ctor должны быть в байтах. Что, возможно, объясняет, почему у вас проблемы с тем, чтобы что-то еще работало? Не думайте, что формат, показанный дизассемблером, соответствует стандарту. - person Hans Passant; 11.06.2010
comment
Действительно, стандарт ECMA ничего не говорит о простом формате, который я использовал для аргументов конструктора. ilasm.exe не имеет проблем с некоторыми из основных типов (строки, целые числа, логические значения, типы и т. д.), но может показаться, что они нестандартны. - person Jono; 14.06.2010