Battle of the INotifyPropertyChanged techniques

Recently at a conference I was given the opportunity to talk about Aspect Orientated programming with PostSharp.  In my demo I showed off the difference between creating an INotifyPropertyChanged class manually, using boilerplate code generated by Resharper, and using smart tags built into PostSharp 3.  By the request of a few, here is what was covered.

What is INotifyPropertyChanged?

It is an interface provided by Microsoft .NET Framework that is used to let client application know when a property has changed.  Typically this will then allow the client to refresh a field to display the changed value.

Initial Setup

In this example lets use this class for as our simple example:

public class Customer{
     public int CustomerId {get; set;}
     public string FirstName {get; set;}
     public string LastName {get; set;}
     public string FullName {get; set;}
     public string Address {get; set;}
}

—- Manually —-

In the beginning we coded stuff manually.

First thing that needs to be done is to add INotifyPropertyChanged to our class.  Add the interface member along with a method to handle the OnPropertyChanged event.  We will now have a class that looks like this:

public class Customer : INotifyPropertyChanged{
     public int CustomerId {get; set;}
     public string FirstName {get; set;}
     public string LastName {get; set;}
     public string FullName {get; set;}
     public string Address {get; set;}

     public event PropertyChangedEventHandler PropertyChanged;

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

Now we can setup our properties to use the OnPropertyChanged method.  Can you spot the error?

public class Customer : INotifyPropertyChanged{
        private string customerFirstName, customerLastName, address;

        public int CustomerId { get; set; }

        public string FirstName{
            get{
                return customerFirstName;
            }

            set{
                if (value != null){
                    customerFirstName = value;
                    this.OnPropertyChanged("FirstName");
                    this.OnPropertyChanged("FullName");
                }
            }
        }

        public string LastName{
            get{
                return customerLastName;
            }

            set{
                if (value != null){
                    customerLastName = value;
                    this.OnPropertyChanged("LastName");
                    this.OnPropertyChanged("FullName");
                }
            }
        }

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

        public string Address{
            get{
                return address;
            }

            set{
                if (value != null){
                    company = value;
                    this.OnPropertyChanged("FirstName");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

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

I hope you spotted the error.

A big problem like this commonly occurs when a developer needs to add a slew of properties like this.  Most of the time out of pure boredom they will eventually just start copy, pasting and modifying the code.  In our example above, we copy pasted the FirstName property and modified that.  When we got to address, we forgot to change the OnPropertyChanged string.

—- Boilerplate —-

Because of the bugs that can be generated by copy paste development, tools like Resharper 7.x+ have built in boilerplate generating functions.  I am not going to go into a lot of detail on this, if you want to read more about this go here.

Through the use of boilerplate code generation and Resharpers smart tags; adding new properties is pretty simple.  With a few clicks our end code looks similar to the end code of the manual process.  So you might be wondering why I still have issues with this, why do I still consider this a mid tier solution.

—- PostSharp 3 —-

PostSharp is a framework that adds Aspect Oriented Programming or AOP to a solution.  This allows developers to separate out boilerplate code (or referenced as cross cutting concerns) from business code.  With PostSharp 3 they introduced the concept of design pattern automation.   If you want to read a great article about this, please go here.

AoP

You can install PostSharp3 from the Visual Studio Extension Gallery.  Once installed right click your solution and select to add PostSharp.  After that go to your class file (notice in the image that it looks like our original code base), from the smart tag select ‘Implement INotifyPropertyChanged’ and watch the magic happen.  The end code will look similar to this:

[NotifyPropertyChanged]
public class Customer{
     public int CustomerId {get; set;}
     public string FirstName {get; set;}
     public string LastName {get; set;}
     public string FullName {get; set;}
     public string Address {get; set;}
}

That is it, don’t believe me… try it and use something like Teleriks JustDecompile or Resharpers dotPeek (Reflector if you have the money for a license.) The code generated in the dll will look similar to our manually and boilerplate code.  In the end which is easier to read, modify, and troubleshoot if a problem arises?

About these ads
This entry was posted in C#, PostSharp and tagged , , . Bookmark the permalink.

One Response to Battle of the INotifyPropertyChanged techniques

  1. jokecamp says:

    Great I was just wondering about NotifyPropertyChanged and aspects. We haven’t made the switch to PostSharp 3 but eager about it now.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s