【问题标题】:How to get the source file name and the line number of a type member?如何获取类型成员的源文件名和行号?
【发布时间】:2008-09-24 08:54:46
【问题描述】:

考虑到调试数据文件可用 (PDB) 并使用 System.Reflection 或其他类似框架(例如 Mono.Cecil),如何以编程方式检索源文件名和声明类型或类型成员的行号。

例如,假设您已将此文件编译为程序集:

C:\MyProject\Foo.cs

1:    public class Foo
2:    {
3:       public string SayHello()
4:       {
5:           return "Hello";
6:       }
7:    }

如何做类似的事情:

MethodInfo methodInfo = typeof(Foo).GetMethod("SayHello");
string sourceFileName = methodInfo.GetSourceFile(); // ?? Does not exist!
int sourceLineNumber = methodInfo.GetLineNumber(); // ?? Does not exist!

sourceFileName 将包含“C:\MyProject\Foo.cs”并且 sourceLineNumber 等于 3。

更新:System.Diagnostics.StackFrame 确实能够获取该信息,但仅限于当前正在执行的调用堆栈范围内。这意味着必须首先调用该方法。我想获得相同的信息,但不调用类型成员。

【问题讨论】:

  • 有新的API,不需要再使用PDB阅读器了,看我的回答
  • 有没有想过这个问题?答案完全忽略了您的问题的重点,即获取任意成员的文件名和行号。不适用于当前... Harold's 是最接近的,但要求每个潜在成员都使用该属性进行装饰...

标签: c# reflection


【解决方案1】:

最新方法:

private static void Log(string text,
                        [CallerFilePath] string file = "",
                        [CallerMemberName] string member = "",
                        [CallerLineNumber] int line = 0)
{
    Console.WriteLine("{0}_{1}({2}): {3}", Path.GetFileName(file), member, line, text);
}

新的Framework API 在运行时填充参数(标有特殊属性), 在my answer to this SO question中查看更多信息

【讨论】:

  • 仅适用于 .Net 4.5 对企业项目的巨大劣势。
  • 我认为您从根本上误解了这个问题。您展示了如何获取有关调用者的信息,但问题询问如何查询任何符号。请参阅 Yann Trevin 对 Richard 回答的评论。
【解决方案2】:

使用上述方法之一,在属性的构造函数中,您可以提供可能具有属性的所有内容的源位置 - 例如类。见以下属性类:

sealed class ProvideSourceLocation : Attribute
    {
        public readonly string File;
        public readonly string Member;
        public readonly int Line;
        public ProvideSourceLocation
            (
            [CallerFilePath] string file = "",
            [CallerMemberName] string member = "",
            [CallerLineNumber] int line = 0)
        {
            File = file;
            Member = member;
            Line = line;
        }

        public override string ToString() { return File + "(" + Line + "):" + Member; }
    }


[ProvideSourceLocation]
class Test
{
   ...
}

你可以这样写:

Console.WriteLine(typeof(Test).GetCustomAttribute<ProvideSourceLocation>(true));

输出将是:

a:\develop\HWClassLibrary.cs\src\Tester\Program.cs(65):

【讨论】:

    【解决方案3】:

    您可能会通过这些链接找到一些帮助:

    Getting file and line numbers without deploying the PDB files 还发现以下post

    “嗨,马克,

    以下将为您提供代码的行号(在 源文件):

    Dim CurrentStack As System.Diagnostics.StackTrace
    MsgBox (CurrentStack.GetFrame(0).GetFileLineNumber)
    

    如果您有兴趣,可以了解一下您的日常活动 in,以及它的所有调用者。

    Public Function MeAndMyCaller As String
        Dim CurrentStack As New System.Diagnostics.StackTrace
        Dim Myself As String = CurrentStack.GetFrame(0).GetMethod.Name
        Dim MyCaller As String = CurrentStack.GetFrame(1).GetMethod.Name
        Return "In " & Myself & vbCrLf & "Called by " & MyCaller
    End Function
    

    如果您想要一个通用的错误例程,这会非常方便,因为它 可以获取调用者的名称(这将是发生错误的地方)。

    问候, 弗格斯 MVP [Windows 开始按钮,关机对话框] "

    【讨论】:

    • 不幸的是,StackTrace 提供了有关当前调用堆栈的信息;而不是任意的外部成员。我想在不实际运行该方法的情况下获取信息。
    • 理查德,busycode 链接坏了。哪里有更新的链接?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 2010-11-19
    相关资源
    最近更新 更多