INotifyPropertyChanged via Extension Methods

I imagine most developers that work with data-binding in WinForms or WPF have their preferred way of implementing INotifyPropertyChanged (or individual <property>Changed events). Normally I use a base class to hide the interface declaration and event and then use helper methods in the setters to take care of raising the event when applicable.

I’ve also spent some time looking at AOP alternatives using PostSharp. These look really promising, but it does require taking a dependency on PostSharp.

Another alternative is to use Extension methods. I had this realisation today and figured I’d spend a few minutes putting together a quick test. Getting the event proved a little irksome, and I’m passing around property names as strings (as opposed to perhaps using a member expression). Here’s the extension class:

public static class PropertyChangedExtension
{
public static void OnPropertyChanged(this INotifyPropertyChanged sender, string propertyName)
{
RaiseEvent(sender, propertyName,  "PropertyChanged");
}
public static void OnPropertyChanging(this INotifyPropertyChanging sender, string propertyName)
{
RaiseEvent(sender, propertyName, "PropertyChanging");
}
public static bool SetValue<T>(this INotifyPropertyChanged sender, 
ref T backingField,
T newValue,
string propertyName) { if ( Equals( backingField, newValue )) return false; var propertyChanging = sender as INotifyPropertyChanging; if (propertyChanging != null) propertyChanging.OnPropertyChanging(propertyName); backingField = newValue; OnPropertyChanged(sender, propertyName); return true; } private static void RaiseEvent(object sender, string propertyName, string eventName) { var fieldInfo = sender.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic); if (fieldInfo != null) { var eventDelegate = fieldInfo.GetValue(sender) as MulticastDelegate; if (eventDelegate != null) eventDelegate.DynamicInvoke(
new object[] { sender, new PropertyChangedEventArgs(propertyName) }); } } }

Here’s a simple test class.

public classPerson: INotifyPropertyChanging, INotifyPropertyChanged

{

    public eventPropertyChangedEventHandler PropertyChanged;

    public eventPropertyChangingEventHandler PropertyChanging;

    private string_firstName;

    private string_lastName;

    public stringFirstName

    {

        get{ return_firstName; }

       
set

      
{

            if(this.SetValue(ref _firstName, value, "FirstName"))

                this.OnPropertyChanged("FullName");

        }

    }

    public string LastName

    {

        get { return _lastName; }

       
set

       
{

            if (this.SetValue(ref _lastName, value, "FirstName"))

                this.OnPropertyChanged("FullName");

        }

    }

    public string FullName

    {

        get { return string.Format("{0} {1}", FirstName, LastName); }

    }

}

Note that I use the boolean result from SetValue to determine whether I should fire property changed events on other dependent properties (again this is something that can be done declaratively using PostSharp).

The RaiseEvent method in the Extension class is a really nasty hack (in other words it won’t always work and is slow). You can simply pass through the event handlers which makes things much simpler, but what I was aiming for was the least amount of code in the setters. I wouldn’t use this code in a production environment (a base class is much better suited). However it is well suited for adding property change notification to classes that I’m just throwing together for a demo or prototype without having to worry about PostSharp dependencies or base classes.