Предотвращение встраивания JIT по методу

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

Проблема возникает, когда я переключаюсь в режим выпуска, где оптимизация включена. Трассировка стека выглядит следующим образом:

> FindActionName at offset 66 in file:line:column <filename unknown>:0:0
> Email at offset 296 in file:line:column <filename unknown>:0:0
> CallingEmailFromRealControllerShouldFindMailersActionName at offset 184
     in file:line:column <filename unknown>:0:0
> _InvokeMethodFast at offset 0 in file:line:column <filename unknown>:0:0
> InvokeMethodFast at offset 152 in file:line:column <filename unknown>:0:0
...

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

2 ответа

Решение

Вы могли бы использовать MethodImplAttribute и указать MethodImplOptions.NoInlining,

[MethodImpl(MethodImplOptions.NoInlining)]
void YourMethod()
{
    // do something
}

Обратите внимание, что это все еще не гарантирует, что вы можете получить фактический вызывающий метод, как видно из исходного кода. Ваш метод не будет встроен, но вызывающий метод может быть встроен в собственный вызывающий и т. Д. И т. Д.

Вы можете использовать дополнительные параметры, отмеченные System.Runtime.CompilerServices.CallerMemberNameAttribute и это братья и сестры CallerFilePath а также CallerLineNumber, Если я правильно понимаю, это должно дать вам правильное имя метода, независимо от того, что указано, а что нет. Однако вы получите только имя метода, я не вижу ничего, чтобы получить имя класса / сборку и т. Д.

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

Правильные способы сделать это, вероятно, будут:

  • Передайте необходимую информацию в качестве параметра
  • Временно сохранить необходимую информацию в Thread.ExecutionContext во время вызова функции

Я понимаю, что это, вероятно, не поможет Скотту после всего этого времени, но, возможно, кто-то еще может извлечь из этого пользу.

Другие вопросы по тегам