7

对于我的 log4net 解决方案,我有一个使用 CallerInfo 属性的 API 包装器,例如

    public void Write(string message,
                            [CallerMemberName] string memberName = "",
                            [CallerFilePath] string filePath = "",
                            [CallerLineNumber] int lineNumber = 0)

但是,我也在使用 Unity 拦截,以便我可以执行之前/之后响应的跟踪记录,例如在 Invoke 方法中使用 ICallHandler,如下所示。

public class TraceCallHandler : ICallHandler
{
...

   public IMethodReturn Invoke(IMethodInvocation input, 
                               GetNextHandlerDelegate getNext)
    {
        //---- Trace method inputs
        this.LogInfoBeforeInvoke(input);

        //---- invoking the target method
        InvokeHandlerDelegate next = getNext();
        IMethodReturn methodReturn = next(input, getNext);

        //---- invoking the target method
        this.LogInfoAfterInvoke(methodReturn.ReturnValue); 
    }
}

注意:上面的代码绝不是完整/正确的......只是想向您展示我为 Unity Interception 所做的工作。

我的问题/挑战是:当我最终调用 log.Write(...) 时,我想要目标的调用者信息,而不是我的 TraceCallHandler 信息。

例如对于方法名称,我可以这样做:

   string methodName = input.MethodBase.Name;

如何获取来电者的文件路径和来电者的行号?甚至可以通过反射来实现吗?

谢谢!

4

2 回答 2

8

是的,您可以使用反射获得这些:

var sf = new System.Diagnostics.StackTrace(1).GetFrame(0);
Console.WriteLine(" File: {0}", sf.GetFileName());
Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber());
// Note that the column number defaults to zero 
// when not initialized.
Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());

但是,正如它在文档中明确指出的那样:

StackFrame 信息将在 Debug 构建配置中提供最丰富的信息。默认情况下,Debug 版本包含调试符号,而 Release 版本不包含。调试符号包含用于构建 StackFrame 对象的大部分文件、方法名称、行号和列信息。

因此,如果您想要的只是调试,请在调试版本中启用它并注销。在发布版本中,尽管它充其量是无用的,最坏的情况是完全误导,因为除了上面的符号考虑之外,编译器会积极地内联方法并重新排序,并且通常会弄乱你的东西。

于 2014-10-23T22:55:22.867 回答
2

我刚刚遇到了这个问题,并想我会分享我学到的东西。首先,当您在方法参数中包含 [CallerFilePath] 时,副作用是文件的完整路径(包括任何用户可识别数据)将包含在您的 .exe 中。我用一种方法创建了一个简单的程序。我创建了一个exe。然后我向测试函数添加了一个 [CallerFilePath] 属性。当我比较 strings.exe(来自 sysinternals)的结果时,具有属性的那个不同,因为它包含了我的源文件的完整路径。

c:\users\<my name>\documents\visual studio 2015\Projects\TestCallerAttribute\TestCallerAttribute\Program.cs

stuartd 上面的答案是正确的,因为您将无法从发布版本中的堆栈跟踪中获取所需的数据。

但是,有一个获取强数据的解决方案:Windows 事件跟踪。来自 msdn:“Windows 事件跟踪 (ETW) 是一种高效的内核级跟踪工具,可让您将内核或应用程序定义的事件记录到日志文件中。您可以实时使用事件或从日志文件中使用并使用它们调试应用程序或确定应用程序中出现性能问题的位置。”

这不是一个快速的解决方案。在设置事件和侦听器以获得所需的出处方面需要做一些工作。长期回报是强劲的。

于 2016-07-28T14:42:04.487 回答