我有一种独特的情况.我一直在开发一个用于发送电子邮件的开源库.在这个库中,我需要一种可靠的方法来获取调用方法.我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
...
Run Code Online (Sandbox Code Playgroud)
这是从失败的单元测试中获得的.在这个跟踪的第3行中,我应该看到一个被称为TestEmail在其他地方定义的方法,但我相信JITter正在内联它.我已经读过你可以通过使方法虚拟来防止内联,但这不起作用.有没有人知道一种可靠的方法来防止方法内联,所以你的方法会出现在堆栈跟踪中?
Luk*_*keH 36
你可以使用MethodImplAttribute和指定MethodImplOptions.NoInlining.
[MethodImpl(MethodImplOptions.NoInlining)]
void YourMethod()
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
请注意,这仍然不能保证您可以获得源代码中看到的实际调用方法.您的方法不会被内联,但您的方法的调用者可以内联到自己的调用者等等.
您可以使用标记的其他参数System.Runtime.CompilerServices.CallerMemberNameAttribute及其兄弟姐妹CallerFilePath和CallerLineNumber.如果我理解正确的话,这应该会为您提供正确的方法名称,无论内容是什么都没有.你只会得到方法名称,我没有看到任何东西来获取类名/汇编等.
应该不用说,但只是为了确定......这样的事情不应该在日志记录/诊断之外使用.
正确的方法可能是:
Thread.ExecutionContext调用函数时临时存储所需信息我意识到这可能对斯科特没有任何帮助,但也许其他人可以从中受益.