Caller Info Attributes in Portable Class Libraries

With the release of .NET 4.5 and Visual Studio 2012, C# and Visual Basic support Caller Info attributes which provide a simple way to get information about the caller of a method.  This can be useful for tracing and diagnostic methods and can also make it easier to implement INotifyPropertyChanged.  For example, you can use a helper method like the following to raise property changed notifications:

 protected bool SetProperty<T>(ref T storage, T value,
                             [CallerMemberName] string propertyName = null)
{
    if (object.Equals(storage, value)) return false;

    storage = value;
    this.OnPropertyChanged(propertyName);
    return true;
}

Then you can write simple properties like this:

 string _title;
public string Title
{
    get { return _title; }
    set { SetProperty(ref _title, value); }
}

This way you don’t have to explicitly specify the name of the property that changed, which means it won’t accidentally get out of sync if you change the property name.  (As a side note, in my opinion this is still more verbose than it should be.  You can use NotifyPropertyWeaver or PropertyChanged.Fody to add property change notification code automatically as a post-compile step.)

Caller Info in Portable Class Libraries

The caller info attributes are part of .NET 4.5, .NET for Windows Store apps, and Windows Phone 8.  If you create a portable library restricted to those targets, you will be able to use the caller info attributes.  If you need to target a platform that doesn’t include these attributes, such as .NET 4, Windows Phone 7, or Silverlight, they won’t be available.

However, the caller info functionality is strictly a function of the compiler, and the compiler doesn’t care where those attributes are defined.  So if you are using the new compiler but targeting an earlier platform, you can define the attributes yourself and get the caller info functionality.  This technique will also work for portable libraries targeting platforms that don’t include these attributes.  So basically, you just need to include the following code in your portable library and you can use caller info attributes on pretty much any platform or portable library.

 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)]
    sealed class CallerMemberNameAttribute : Attribute { }

    // 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:
    //     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 { }
}