22

考虑到调试数据文件可用 (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确实能够获得该信息,但仅限于当前执行的调用堆栈范围内。这意味着必须首先调用该方法。我想获得相同的信息,但不调用类型成员。

4

3 回答 3

10

最新方法:

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功能,请参阅我对这个 SO 问题的回答

于 2013-04-30T08:59:32.163 回答
3

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

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):
于 2014-10-17T19:10:30.083 回答
-1

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

在不部署 PDB 文件的情况下获取文件和行号 也发现了以下帖子

“嗨,马克,

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

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

如果您有兴趣,您可以了解您所在的例程以及所有调用者。

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

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

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

于 2008-09-24T09:06:08.493 回答