Атрибут для разметки раздела MSIL - PullRequest
0 голосов
/ 11 июля 2020

Есть ли механизм для пометки места в коде, которое будет переносить этот тег в сгенерированный MSIL?

Это было бы полезно при поиске определенной части большого метода, вместо того, чтобы читать все MSIL, чтобы найти нужный раздел.

В настоящее время я просто помещаю строковую переменную, на которую нет ссылки. Это будет отображаться в отладочной сборке, но не в производственной сборке, но это взлом, и я надеялся, что может быть правильный способ. Например, атрибут компилятора или что-то в этом роде, но я ничего не могу найти.

За первый комментарий, добавление дополнительных деталей ... Это раздел MSIL для большого метода. Он соответствует строке кода C#, для которой я хочу увидеть сгенерированный MSIL:

  • ...
  • IL_0645: stlo c .s nLon
  • IL_0647: ldlo c .s ofs
  • IL_0649: ldarg.1
  • IL_064a: bge.s IL_0660
  • IL_064 c: ldlo c .0
  • IL_064d: ldlo c .s of
  • IL_064f: dup
  • IL_0650: ld c .i4.1
  • IL_0651: добавить
  • IL_0652: stlo c .s of
  • IL_0654: conv.i
  • IL_0655: ld c .i4.2
  • IL_0656 : mul
  • IL_0657: add
  • IL_0658: ldind.u2
  • IL_0659: dup
  • ...

My вопрос в том, есть ли простой способ найти этот раздел с помощью аннотации или ??, кроме чтения из IL_0000 и следования более 600 строкам кодов MSIL.

Спасибо

1 Ответ

0 голосов
/ 25 июля 2020

К сожалению, не существует механизма для вставки атрибута непосредственно в поток IL, но вы можете «злоупотребить» обработкой исключений, чтобы отметить сегмент кода с помощью try / catch:

static void MarkedMethod()
{
    Console.WriteLine("A");
    try
    {
        Console.WriteLine("B");
    }catch(Marker)
    {
        throw;
    }
    Console.WriteLine("C");
}

sealed class Marker : Exception
{
    private Marker() { }
}

var body = ((Action)MarkedMethod).Method.GetMethodBody();
foreach(var cl in body.ExceptionHandlingClauses)
{
    if(cl.Flags == ExceptionHandlingClauseOptions.Clause && cl.CatchType.Equals(typeof(Marker)))
    {
        Console.WriteLine(cl.TryOffset + ", " + cl.TryLength);
    }
}

try в любом случае должен быть довольно легким, поэтому, если предположить, что блок catch никогда не вводится, это не должно иметь большого влияния

...