Wednesday, October 31, 2012

C# 5: Caller Information

.NET 4.5 has introduced a few new classes that will enable more detailed logging, debugging and tracing through your code.  Today, I will focus on the following classes:

1. The CallerMemberNameAttribute class is used by appending it as an optional parameter on a method.  When the method is called, it will contain the method or property name which made the current call into this method.
2. The CallerFilePathAttribute class is used by appending it as an optional parameter on a method.  When the method is called, it will contain the code file path to the C# source code file that made the current call into this method.
3. The CallerLineNumberAttribute class is used by appending it as an optional parameter on a method.  When the method is called, it will contain the code file line number within the C# source code file that made the current call into this method.

Grabbing all of this information will enable you to create very detailed logging and trace statements.  This will ultimately aid you in trouble-shooting code issues or errors encountered by users running your application.  Below is a usage example of these attributes and the run-time logging potential they make available.

namespace CallerInformation
{
    class Program
    {
        static void Main(string[] args)
        {   
            MethodA();
            MethodB();
            Console.ReadLine();
        }

        static void MethodA([CallerMemberName] string memberName = "",
               [CallerFilePath] string sourceFilePath = "", 
               [CallerLineNumber] int sourceLineNumber = 0)
        {
            InsertLog(memberName, "MethodA", sourceFilePath, sourceLineNumber); 
            MethodB();
        }

        static void MethodB( [CallerMemberName] string memberName = "",
               [CallerFilePath] string sourceFilePath = "",  
               [CallerLineNumber] int sourceLineNumber = 0)
        {
            InsertLog(memberName, "MethodB", sourceFilePath, sourceLineNumber);
        }

        static void InsertLog(string methodName, String calledMethodName, 
               String sourceFilePath, Int32 sourceLineNumber)
        {
            Console.WriteLine("{0} called {1} from file:'{2}' line: {3}",
              methodName, calledMethodName, 
              sourceFilePath, sourceLineNumber.ToString());

        }
    }
}

In the output from this application, notice that the calls to MethodB() both form the Main method as well as MethodA() contains the correct information regarding the source object, file and line number.


While possible to rely upon your exception handling plan to provide call stack information, you are also able to build on the base for your own purposes.  By accessing these values as well as any local data, variable values and session specific information, you can build and handle messages that present you with all of the information needed to troubleshoot user errors, debug intricate processes or supply more complex audit trail logging within your system.