Dmitry Shechtman's Blog

December 12, 2009

INotifyPropertyChanged with Unity Interception AOP

Background

If you have ever developed a non-trivial application in WPF, you’ll probably find this familiar:

    public class ProductFamilyViewModel : INotifyPropertyChanged
    {
        private bool isSelected;
        public bool IsSelected
        {
            get { return isSelected; }
            set
            {
                if (isSelected != value)
                {
                    isSelected = value;
                    SendPropertyChanged("IsSelected");
                }
            }
        }

        private bool isExpanded;
        public bool IsExpanded
        {
            get { return isExpanded; }
            set
            {
                if (isExpanded != value)
                {
                    isExpanded = value;
                    SendPropertyChanged("IsExpanded");
                }
            }
        }

        private bool isActive;
        public bool IsActive
        {
            get { return isActive; }
            set
            {
                if (isActive != value)
                {
                    isActive = value;
                    SendPropertyChanged("IsActive");
                }
            }
        }

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

        public event PropertyChangedEventHandler PropertyChanged;
    }

(This is an excerpt from a real class I’ve been working on; the actual code is bigger and uglier.)

Isn’t it sad that you have auto-implemented properties, but not the ability to use them? Wouldn’t you love to be able to do something like that?

[NotifyPropertyChanged]
public class ProductFamilyViewModel : MarshalByRefObject, INotifyPropertyChanged
{
    public bool IsSelected { get; set; }
    public bool IsExpanded { get; set; }
    public bool IsActive { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
}

This has been achieved (with varying levels of success) with DynamicProxy2 and repeatedly with PostSharp (reportedly refined in PostSharp 2.0), but what about Microsoft Enterprise Library?

At first, the Policy Injection Application Block might look like the perfect tool for the task, but looks are often deceiving; quoting Richard Banks:

Windsor and PIAB both have a shortfall that we can’t overcome.  Neither of them can alter the type of a class they are providing aspects for – they simply provide proxies that add hooks to intercept method calls.  We would still need to implement INotifyPropertyChanged in our class for binding to work.

Not to fret! Luckily, Enterprise Library 4.1 ships with the Unity Application Block (also available as a separate download). Unity, in turn, contains the mighty Interception Extension, which seems to be getting undeservedly little attention from developers. I guess this has to do with its poor documentation and lack of UI configuration support (expected to be added in 5.0).

None of these, however, have prevented Derek Greer from trying. His post contains a great introduction to Unity Interception (Prolegomena is definitely recommended) and quite a few insights, but sadly falls short of achieving the ultimate goal.

This article details a complete user-friendly implementation of the INotifyPropertyChanged aspect using Unity Interception AOP. It is the first in a planned series of articles concerning AOP with Unity Interception and Policy Injection:

  1. INotifyPropertyChanged AOP
  2. IDataErrorInfo AOP
  3. Policy Injection
  4. Performance and optimizations
  5. The final solution

I hope you will find this useful in your work; all feedback will be greatly appreciated.

Note: The implementation presented below is limited to classes derived (possibly indirectly) from MarshalByRefObject.

Update 2009-12-14: Dima Gershman, a truly knowledgeable colleague of mine, says go with the looks. Policy Injection wraps user objects with Interception’s transparent proxies, relieving us of the burden of manual configuration (and even improving performance!), although that comes at the price of some extra library dependencies. To be continued…

(more…)

Advertisements

Create a free website or blog at WordPress.com.