34

我有一种独特的情况。我一直在开发一个用于发送电子邮件的开源库。在这个库中,我需要一种可靠的方法来获取调用方法。我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 正在内联它。我读过你可以通过使方法虚拟来防止内联,但这不起作用。有谁知道防止方法内联的可靠方法,因此您的方法将显示在堆栈跟踪中?

4

2 回答 2

42

您可以使用MethodImplAttribute并指定MethodImplOptions.NoInlining.

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

请注意,这仍然不能保证您可以使用源代码中看到的实际调用方法。你的方法不会被内联,但你的方法的调用者可以被内联到它自己的调用者等等。

于 2011-03-02T14:57:04.547 回答
7

您可以使用标有的附加参数System.Runtime.CompilerServices.CallerMemberNameAttribute,它的兄弟姐妹CallerFilePathCallerLineNumber. 如果我理解正确,这应该为您提供正确的方法名称,无论内联的是什么,什么不是。但是,您只会获得方法名称,我看不到任何获得类名/程序集等的东西。

它应该不言而喻,但只是为了确定......这样的东西应该在日志/诊断之外使用。

正确的方法可能是:

我意识到,经过这么长时间,这可能对 Scott 没有任何帮助,但也许其他人可以从中受益。

于 2013-01-11T15:19:47.077 回答