Custom Refactor Pro Plug-in – Convert Property

UPDATE: Thanks to some excellent feedback from Rory Becker, I changed my plug in from a Refactor provider to a Code provider. A refactoring should be structural and should not change the functionality of the code, whereas this plug in changes behavior. That just means the prompting is a little different as shown in the updated screen grab below. I also made it work for VB as well with some more help from the DevExpress folks. The code download at the bottom gives you the latest version.

Something I frequently find myself doing is starting a type out with simple, auto-implemented properties in C# along these lines:

public string Name { get; set; }

 

Then at some point I realize I want that type to implement INotifyPropertyChanged and have that property and possibly some of the others raise PropertyChanged notifications when they change. I got really tired of doing this manually, and my first way of automating it was to just create a code snippet for a property changed notification property, and I would overwrite the simple property with the property changed property.

But then I found myself needing to see if INotifyPropertyChanged was already implemented, if not add it, resolve it, see if the property already had a backing member variable, if not add it, yadda yadda… screaming for automation.

Unfortunately code snippets in VS are not that powerful, but fortunately I already use a tool that I think every developer should have on their desktop – CodeRush + Refactor Pro.

These two products are built on top of an extensibility engine called DxCore, which allows them as well as VS to be extensible based on a fairly straightforward API (that is all managed code, unlike the VS extensibility model).

In this case what I really wanted was an intelligent refactoring where I could just right click on an existing property, have it figure out if it had a member variable or not, if not add one, see if the type had INotifyPropertyChanged implemented, if not add it, add the using statement for System.ComponentModel if it was not already there, and add the PropertyChanged event with an anonymous method subscriber (so that you don’t need to null check and don’t have to worry about multithreaded race conditions with unsubscribing).

With a few hints and a starter project from my friends at DevExpress I got a Refactor Pro plug-in working in no time that does just that. I can invoke Refactor Pro (keystroke or a mouse click) on a simple property (auto-backing member or not) and get this:

refactor

When I invoke the conversion, it adds the INotifyPropertyChanged implementation if needed. So the following simple class:

public class Customer
{
    public string Name { get; set; }
}

 

Becomes this:

public class Customer : INotifyPropertyChanged
{
    string m_Name;
    public string Name
    {
        get
        {
            return m_Name;
        }
        set
        {
            if (value != m_Name)
            {
                m_Name = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Name"));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

It also adds the using statement for System.ComponentModel if not already present. If I invoke it on another simple property in that class, it just adds the expanded property syntax and leaves the type declaration alone.

The code is a little too long to list here, but you can download the plug-in code here. If there is enough demand through comments, I’ll do a follow on post with a walk through of the code.

Comments are closed.