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…

Project

We’ll start by creating a Class Library project and adding the following reference to it:

  • Microsoft.Practices.Unity.Interception

Quite a small dependency toll, isn’t it? Using our library will require some additional references (depending on the configuration strategy), which will be detailed below.

Note: Although the assembly name is Microsoft.Practices.Unity.Interception.dll, the namespace is Microsoft.Practices.Unity.InterceptionExtension. This significant source of confusion (especially considering the lack of configuration editor support) will hopefully be eliminated in EntLib 5.0.

Update 2009-12-12: Removed unneeded reference to Microsoft.Practices.Unity.

Matching Rules

Let’s have another look at the desired syntax:

[NotifyPropertyChanged]
class Class1 : MarshalByRefObject, INotifyPropertyChanged
{
    public int MyProperty { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
}

NotifyPropertyChangedAttribute is the easiest part:

[Serializable, AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class NotifyPropertyChangedAttribute : Attribute { }

Update 2009-12-19: Enabled inheritance.

Next, we’ll need to specify the rules to be used to intercept the methods (or setters, in our case), namely

  1. public setters
  2. defined in types decorated with NotifyPropertyChangedAttribute.

The following matching rule types are provided out of the box:

  • AssemblyMatchingRule
  • AttributeDrivenPolicyMatchingRule
  • CustomAttributeMatchingRule
  • MemberNameMatchingRule
  • MethodSignatureMatchingRule
  • NamespaceMatchingRule
  • ParameterTypeMatchingRule
  • PropertyMatchingRule
  • ReturnTypeMatchingRule
  • TagAttributeMatchingRule
  • TypeMatchingRule

PropertyMatchingRule is perfect for the first rule; we’ll simply specify * as propertyName and Set as option.

The second rule is a bit trickier.

Let’s look at TagAttributeMatchingRule. This class matches TagAttribute (duh!):

[Tag("NotifyPropertyChanged")]
class Class1 : MarshalByRefObject, INotifyPropertyChanged

However, such approach is prone to typos, since constants cannot be used as attribute parameters.

AttributeDrivenPolicyMatchingRule matches method parameters:

public int MyProperty
{
    get;
    [Notify] set;
}

which is somewhat closer to our requirement, but is still error-prone. Ideally, we’d decorate the entire class with our custom attribute and leave the auto-implemented properties, well, auto-implemented.

This calls for a mix between CustomAttributeMatchingRule, TagAttributeMatchingRule and TypeMatchingRule. How does one interbreed between three different species? Luckily, we’re not in the field of biology, so this is fairly easy:

public class CustomTypeAttributeMatchingRule : IMatchingRule
{
    private readonly Type attributeType;
    private readonly bool inherited;

    public CustomTypeAttributeMatchingRule(Type attributeType, bool inherited)
    {
        if (attributeType == null)
            throw new ArgumentNullException("attributeType");
        if (!attributeType.IsSubclassOf(typeof(Attribute)))
            throw new ArgumentException("The specified type is not a subclass of Attribute", "attributeType");

        this.attributeType = attributeType;
        this.inherited = inherited;
    }

    public bool Matches(MethodBase member)
    {
        if (member == null)
            throw new ArgumentNullException("member");

        object[] attributes = member.ReflectedType.GetCustomAttributes(attributeType, inherited);
        return attributes != null && attributes.Length > 0;
    }
}

The most surprising to me was the fact that nobody (starting with Microsoft) had implemented this beforehand. This is mostly a copy-and-paste job, so I can’t really claim copyright for the implementation, just for the idea :)

Call Handler

Now that we have the matching rules defined, let’s proceed to the call handler:

public class NotifyPropertyChangedCallHandler : ICallHandler

Implementing the interface methods:

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
    bool shouldRaise = ShouldRaiseEvent(input);
    IMethodReturn res = getNext()(input, getNext);
    if (res.Exception == null && shouldRaise)
        RaiseEvent(input);
    return res;
}

public int Order { get; set; }

The event isn’t raised if an exception has been thrown by the setter.

private bool ShouldRaiseEvent(IMethodInvocation input)
{
    MethodBase methodBase = input.MethodBase;
    if (!methodBase.IsSpecialName || !methodBase.Name.StartsWith("set_"))
        return false;

    string propertyName = methodBase.Name.Substring(4);
    PropertyInfo property = methodBase.ReflectedType.GetProperty(propertyName);
    MethodInfo getMethod = property.GetGetMethod();
    if (getMethod == null)
        return false;
    object oldValue = getMethod.Invoke(input.Target, null);
    object value = input.Arguments[0];

    return value == null ?
        value != oldValue :
        !value.Equals(oldValue);
}

First, we make sure that we are dealing with a setter (this part is borrowed from Derek’s class). Then, we use reflection to check that the new value is accessible via a public getter (check added 2009-12-14) and is actually different from the old one. The ternary operator takes care of unboxing.

private void RaiseEvent(IMethodInvocation input)
{
    FieldInfo field = null;
    for (Type type = input.methodBase.ReflectedType;
        (field = type.GetField("PropertyChanged", BindingFlags.Instance | BindingFlags.NonPublic)) == null;
        type = type.BaseType)
        ;

    MulticastDelegate evt = field.GetValue(input.Target) as MulticastDelegate;
    if (evt != null)
    {
        string propertyName = input.MethodBase.Name.Substring(4);
        evt.DynamicInvoke(input.Target, new PropertyChangedEventArgs(propertyName));
    }
}

In order to raise the event, we walk up the inheritance chain in search for the event’s field, cast it to MulticastDelegate and dynamically invoke the delegates.

This concludes our multicast for today. Since design-time configuration calls for a lengthy explanation, we’ll deal with usage in a separate article.

Update 2009-12-14: Added check for public getter.

About these ads

20 Comments »

  1. […] INotifyPropertyChanged AOP […]

    Pingback by IDataErrorInfo with Validation Application Block and Unity Interception AOP « Dmitry Shechtman's Blog — December 19, 2009 @ 12:40

  2. I’ve been looking for a way out of the get/set drudgery for a while and this looks like the answer :)

    Dmitry, would you mind if I incorporated that code into my WPF Starter Kit over at http://wpfstarterkit.codeplex.com ?

    Comment by Arunjeet Singh — December 30, 2009 @ 09:51

    • Sure, feel free to use the code as you like, although I believe it’s best to wait for the “official release” (I’m working on it).

      Anyway, it’s great to know that I’m not the only one who thinks this stuff is useful :) Good luck with the Kit!

      Comment by Dmitry Shechtman — December 30, 2009 @ 10:11

      • Could you provide a working example you described solutions

        Comment by Grigor — July 21, 2010 @ 20:11

  3. […] Echad un post a INotifyPropertyChanged with Unity Interception AOP del blog de Dmitry Shechtman que me ha servido de inspiración para el ejemplo (yo […]

    Pingback by Objetos que notifican sus cambios de propiedades (1/3): La intercepción - Burbujas en .NET — January 13, 2010 @ 14:36

  4. Hi Dmitry,

    I’m trying to make this work for me. But I’m missing some code I think, and I’m very new to unity. How do I add this functionality to my program. I believe I have to use a unity container with the AddNewExtension method? Can you give a small example?

    Thanks
    Robert

    Comment by Robert — March 1, 2010 @ 11:07

    • Hi Robert,

      Welcome to my blog; apologies for the late reply.

      The best way to make it work is Policy Injection. I was planning to follow up with details, but failed to do so due to seemingly low interest from readers.

      Here’s a quick code snippet for you:

      Interception interception = new Interception();
      container.AddExtension(interception);
      interception.AddPolicy("NotifyPropertyChanged")
      .AddMatchingRule(new CustomTypeAttributeMatchingRule(typeof(NotifyPropertyChangedAttribute), false))
      .AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set))
      .AddCallHandler();

      You’ll have to either Resolve() or BuildUp() your view models.

      The problem with this approach lies with the need to register an interceptor for each view model class.

      Hope this helps,
      Dmitry

      Comment by Dmitry Shechtman — March 4, 2010 @ 21:45

  5. Hi Dmitry

    What a great sound of AOP implementation series. I really love them!
    We are using PostSharp now as our Aspects implementations, but it seems could be replaced by your nice way of thinking and integrated solution of owner’s (Microsoft Unity ;), due to licensing of PostSharp 2.0 in VS2010 and becoming commercial product after experiencing a successfull open source story :)
    Anyway, I am very thankful for your solution and I will consider to using this instead of PostSharp, Hopefully having all things together here.
    I will contact you during implementation, possibly facing errors or lack of my knowledge.

    Regards

    Comment by Sadegh — April 21, 2010 @ 20:36

  6. Is there any test project, where I can see how it it implemented and used?

    Comment by Alex — June 25, 2010 @ 14:54

  7. Hi Alex

    You are right, but it is for limitation of this section which is not support file attachments.Anyway, please provide me an email address to sending the sample projects I worked.However, I applied this implementation to standard project of MVVM pattern by Josh Smith in the following link.

    http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

    I’m looking forward to your reply and email address.
    Regards

    Comment by Sadegh — June 27, 2010 @ 07:41

    • Sadegh,

      I suggest that you publish your projects elsewhere and link to them rather than ask for email addresses.

      Thank you.

      Comment by Dmitry Shechtman — June 27, 2010 @ 14:09

      • Dmitry,
        I am very thankful for your advise.
        I already uploaded my sample project solution which is originally MVVM demo application by Josh Smith and I applied your AOP solution for INPC, However, it seems to not working properly.

        http://rapidshare.com/files/403968131/MvvmDemoApp-AOP.rar.html

        I would be very grateful if you review my implementaion and your help would be greatly appreciated.

        Sadegh

        Comment by Sadegh — June 30, 2010 @ 07:01

  8. Hi Dmitry,

    I give up… I am pretty new to whatever-injection let alone the Enterprise Library. However, since it is a common library used by many of our clients, I believe it’s the best way to make use of it integrated DI Containers.

    I would now like to implement an “aspect” for the INotifyPropertyChanged interface. However, like others also found out: The part that makes everything work is unfortunately missing in your post… and I just cant get unity to work… or better: Everything seems to be working, but unfortunately the methods don’t get called.

    Could you please please invest an hour and post another article that at least puts all pieces together?

    That would be really awesome!!
    Thanks,
    Christian.

    Comment by Christian Jacob — November 19, 2010 @ 14:17

  9. That is a most awesome demonstration of the power of Unity and AOP. I’ve linked this article into a discussion on best practices for implementing INotifyPropertyChanged at http://compositeextensions.codeplex.com/discussions/53731. Hopefully this will become the default way of doing things for Unity users!

    Comment by David Keaveny — February 17, 2011 @ 02:11

  10. Hi, Dmitry!
    I am very thankful for the acticle.I was looking on Unity and his AOP possibilities. This article inspires!

    Comment by Tatiana — March 26, 2011 @ 08:26

  11. […] that a property was set”, so first we will add a ShouldRaiseEvent method (see this post) except, that we will return true when there are no […]

    Pingback by [EN] #NET #Unity container and INotifyPropertyChanged and POCO « Marcin Dembowski — April 28, 2011 @ 20:14

  12. […] INotifyPropertyChanged with Unity Interception AOP « Dmitry Shechtman’s Blog […]

    Pingback by Web Links « AMPT Blog — July 13, 2011 @ 16:06

  13. […] INotifyPropertyChanged With Unity Interception AOP […]

    Pingback by Simplest way to achieve automatic notification of property change | Ask Programming & Technology — November 5, 2013 @ 00:42

  14. […] See: http://shecht.wordpress.com/2009/12/12/inotifypropertychanged-with-unity-interception-aop/ […]

    Pingback by WPF Notes | Programming — January 16, 2014 @ 05:50


RSS feed for comments on this post. TrackBack URI

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

The Shocking Blue Green Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 309 other followers