Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the source file name and the line number of a type member?

Tags:

c#

reflection

Considering that the debug data file is available (PDB) and by using either System.Reflection or another similar framework such as Mono.Cecil, how to retrieve programmatically the source file name and the line number where a type or a member of a type is declared.

For example, let's say you have compiled this file into an assembly:

C:\MyProject\Foo.cs

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

How to do something like:

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

sourceFileName would contain "C:\MyProject\Foo.cs" and sourceLineNumber be equal to 3.

Update: System.Diagnostics.StackFrame is indeed able to get that information, but only in the scope of current executing call stack. It means that the method must be invoked first. I would like to get the same info, but without invoking the type member.

like image 254
Yann Trevin Avatar asked Sep 24 '08 08:09

Yann Trevin


2 Answers

Up to date method:

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);
}

New Framework API which populates arguments (marked with special attributes) at runtime, see more in my answer to this SO question

like image 55
illegal-immigrant Avatar answered Oct 19 '22 10:10

illegal-immigrant


Using one of the methods explained above, inside the constructor of an attribute, you can provide the source location of everything, that may have an attribute - for instance a class. See the following attribute class:

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
{
   ...
}

The you can write for instance:

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

Output will be:

a:\develop\HWClassLibrary.cs\src\Tester\Program.cs(65):
like image 3
Harald Hoyer Avatar answered Oct 19 '22 10:10

Harald Hoyer