Дефиниране на персонализирани атрибути в 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 няма проблем с няколко от основните типове (низове, int, bools, типове и т.н.), но изглежда, че те са нестандартни. - person Jono; 14.06.2010