Introduction
Previously if any exception occurs in the program, it was bit tough to write method names and path details in the error log message. From Visual studio 2012, Microsoft has introduced a new concept called "Caller Information".
Caller Information - Can get the caller method information using Caller Info attributes provided by System.Runtime.CompilerServices namespace. The information can be used for debugging and tracing purpose.
Caller Info attributes:
Caller Information has 3 attributes shipped with it. They are
- CallerFilePathAttribute - source file path at compile time from the caller ( DataType: String )
- CallerLineNumberAttribute - source line number at which method is caller ( DataType: int )
- CallerMemberNameAttribute - member name of caller. ( DataType: String ).
Example (C#.NET):
using System;
using System.Runtime.CompilerServices;
public class CallerInformationProgram
{
private static void Main(string[] args)
{
try
{
int zero = 0;
int result = 1 / zero;
}
catch (Exception ex)
{
LogError(ex.Message);
}
}
private static void LogError(string errMessage,
[CallerMemberName] string memberName = null,
[CallerFilePath] string sourceFilePath = null,
[CallerLineNumber] string sourceLineNumber = 0)
{
string message = string.Format(" Exception Message : {0} \n Member Name : {1} \n File Path : {2}\n Line Number : {3}",
errMessage,
memberName,
sourceFilePath,sourceLineNumber
);
Console.WriteLine(message);
Console.ReadLine();
}
}
Example (VB.NET version):
Imports System.Runtime.CompilerServices
Public Class CallerInformationProgram
Private Shared Sub Main(args As String())
Try
Dim zero As Integer = 0
Dim result As Integer = 1 \ zero
Catch ex As Exception
LogError(ex.Message) 'caller is equivalent to LogError(ex.Message,"Main","d:\practice\CallerInformationProgram.vb",15)
End Try
End Sub
Private Shared Sub LogError(errMessage As String,
<CallerMemberName> Optional memberName As String = Nothing,
<CallerFilePath> Optional sourceFilePath As String = Nothing,
<CallerLineNumber> Optional sourceLineNumber As Integer = 0)
Dim message As String = String.Format("Exception Message : {0}. " & vbLf &
" Member Name : {1}. " & vbLf &
" File Path : {2} " & vbLf &
" Line Number : {3}",
errMessage, memberName, sourceFilePath, sourceLineNumber)
Console.WriteLine(message)
Console.ReadLine()
End Sub
End Class
output:
Exception Message : Attempted to divide by zero.
Member Name : Main
File Path : d:\practise\CallerInformationProgram.cs
Line Number : 15 (Note: Line Number "15" is the location where we called LogError method not the line number at which error has occurred.)
If you observe the program, we have passed only exception message to LogError method but we are able to extract more details( Member Name, File Path and Line Number) using Caller Information.
More details about Caller Info attributes:
- "Caller Info attributes" are sealed classes inherited from Attribute class
- Classes are defined under System.Runtime.CompilerServices namespace.
- In the method you can use any combination of 3 attributes and should be defined after all required parameters because these attributes treated as Optional parameters.
- You must specify an explicit default value for each optional parameter.If you remove explicit default values for the attributes we will get Compile Error as "The CallerMemberNameAttribute/CallerMemberName/CallerFilePath may only be applied to parameters with default values"
- For CallerMemberNameAttribute Member names comes differently. some of them are
- Method/Event/Property - Method/Event/Property Name
- Constructor - ".ctor"
- Destructor - "Finalize"
- Static constructor - ".cctor"
Caller Info attributes class Definitions:
For the reference we tried to copy the class definitions for Caller Info attributes from System.Runtime.CompilerServices namespace.
using System;
namespace System.Runtime.CompilerServices
{
// Summary:
// Allows you to obtain the method or property name of the caller to the method.
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class CallerMemberNameAttribute : Attribute
{
// Summary:
// Initializes a new instance of the System.Runtime.CompilerServices.CallerMemberNameAttribute
// class.
public CallerMemberNameAttribute();
}
// Summary:
// Allows you to obtain the full path of the source file that contains the caller.
// This is the file path at the time of compile.
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class CallerFilePathAttribute : Attribute
{
// Summary:
// Initializes a new instance of the System.Runtime.CompilerServices.CallerFilePathAttribute class.
public CallerFilePathAttribute();
}
// Summary:
// Allows you to obtain the line number in the source file at which the method is called.
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
public sealed class CallerLineNumberAttribute : Attribute
{
// Summary:
// Initializes a new instance of the System.Runtime.CompilerServices.CallerLineNumberAttribute class.
public CallerLineNumberAttribute();
}
}