我有一种独特的情况。我一直在开发一个用于发送电子邮件的开源库。在这个库中,我需要一种可靠的方法来获取调用方法。我通过分析其中的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正在内联它。我已经读过你可以通过使方法虚拟来防止内联,但这不起作用。有没有人知道一种可靠的方法来防止方法内联,所以你的方法会出现在堆栈跟踪中?
答案 0 :(得分:34)
您可以使用MethodImplAttribute
并指定MethodImplOptions.NoInlining
。
[MethodImpl(MethodImplOptions.NoInlining)]
void YourMethod()
{
// do something
}
请注意,这仍然不能保证您可以获得源代码中看到的实际调用方法。您的方法不会被内联,但您的方法的调用者可以内联到自己的调用者等等。
答案 1 :(得分:5)
您可以使用标有System.Runtime.CompilerServices.CallerMemberNameAttribute
的其他参数及其兄弟CallerFilePath
和CallerLineNumber
。如果我理解正确的话,这应该会为您提供正确的方法名称,无论内容是什么都没有。你只会获得方法名称,我没有看到任何东西来获取类名/汇编等。
不言而喻,但只是为了确定......这样的事情应该不在日志记录/诊断之外使用。
这样做的正确方法可能是:
Thread.ExecutionContext
中
我意识到这可能对斯科特没有任何帮助,但也许其他人可以从中受益。