Getting caller information in C# 5.0

In application log files, sometimes it is really useful to see the name of the method that wrote the log, the source file and the line number. If we were using C++, this information would be readily available to the logger using some convenient macros. But if we are programming in C# 4.0 or earlier, we had no way to get that information automatically if we don’t have the debugging symbols (except for the method name) and we don’t usually deploy the pdbs along with the binaries. Even if we did, the line number is almost always different between debug and release builds. Unless we build our binaries in debug mode and then deploy the pdbs along with the binaries, which is not usually the case, we are out of luck. The other disadvantages of using the StackFrame class to get the method information is that it is slow and if your code is obfuscated, the name of the calling method will not be what we expect.

The way I have seen it in most logging code in C# is the calling method’s name is passed into the logging method as a string but the caller’s source file and line number are usually not logged. Although it is possible to pass in all this info to the logging method, it is such a chore and a maintenance nightmare. The name of the method, the source file and line number can all easily change and one can just as easily forget to update the logging code. Anyway who wants to pass in all that information when all they want to do is log a message.

C# 5.0 introduces a way to get the caller information in an easy and non-intrusive way. While the design is not what I would call the most intuitive, I am happy that it works with minimal disruption to our existing code. We can get three pieces of caller information using three attributes that can be applied to optional parameters of a method which is interested in getting information about its caller. The attributes are

  • CallerMemberNameAttribute
  • CallerFilePathAttribute
  • CallerLineNumberAttribute

Here is an example of how we will use these attributes:

    publicstaticclassLogger

    {

        publicstaticvoid Log(

            string message,

            [CallerMemberName] string caller = “”,

            [CallerFilePath] string filePath = “”,

            [CallerLineNumber] int lineNumber = 0)

        {

            Console.WriteLine(

                “{0}. Caller {1}, src file: {2} on line #: {3}”,

                message,

                caller,

                filePath,

                lineNumber);

        }

    }

The compiler will automatically fill in the correct values for these optional parameters at compile time. How convenient !

Read more here.

2 Comments

  1. You are welcome 🙂
    StackFrame.GetMethod() has a notable disadvantage. If the code has been obfuscated, then we don’t get the correct method names at runtime. But for this new attribute based approach, the values are embedded into the code at compile time, so obfuscation should not have any effect.

Leave a Comment

Your email address will not be published. Required fields are marked *