Simplifying INotifyPropertyChanged with CallerMemberName

I’m a bit late to the party as I only just discovered a somewhat hidden gem in .NET 4.5. I’d always considered INotifyPropertyChanged to be somewhat painful to use, because of the need to trigger the PropertyChanged event, thus precluding the usage of automatic properties. Sadly, this part hasn’t gone anywhere, but at least using the PropertyChanged event itself is somewhat easier now with the CallerMemberNameAttribute.

I’d earlier used something like this:

public class Counter : INotifyPropertyChanged
{
    private int _count = 0;
    public int Count
    {
        get { return _count; }
        set {
            if (value != _count) {
                _count = value;
                NotifyPropertyChanged("Count");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The problem with this is that if I refactor the name of the property to something else, refactoring tools won’t know to change the propertyName parameter in the NotifyPropertyChanged call accordingly. It was possible to work around this in earlier .NET versions by using reflection to get the name of the changed property (only changed parts below):

    public int Count {
        get { return _count; }
        set {
            if (value != _count) {
                _count = value;
                NotifyPropertyChanged(() => this.Count);
            }
        }
    }

    protected void NotifyPropertyChanged<T>(Expression<Func<T>> propertyExpression)
    {
        var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
        this.NotifyPropertyChanged(propertyName);
    }

This looks a bit awkward and scary to new developers, with its use of the lambda expression and Expression and Func templates (I know I was intimidated by that many years ago when I saw it in the Prism sample codes – the code is nicked from Prism, just adapted to the names I’ve used earlier).

Happily, with CallerMemberNameAttribute, I no longer need this extra complication, and can just do:

    public int Count {
        get { return _count; }
        set {
            if (value != _count) {
                _count = value;
                NotifyPropertyChanged();
        }
    }

    protected void NotifyPropertyChanged([CallerMemberName] propertyName = "")
    {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

A yet different option is to use IL Weaving to inject the notifications in a post-build step, for example with the Fody PropertyChanged add-in, but I’ve not tried these yet, probably due to some reluctance on my part to have tools muck with my assemblies.

Of course, I’d love it if support for INotifyPropertyChanged were provided through syntactic sugar in C# itself, for example through something like

    public notify int Count { get; set; }

where “notify” is my hypothetical keyword for defining a notifying property.

No comments yet.

Leave a Reply