Latest Tweet:
  • Loading...

As a WPF or Silverlight developer chances are you have implemented the INotifyPropertyChanged-interface more than once. The interface is simple enough, consisting of a single PropertyChanged-event. The data binding infrastructure in WPF and Silverlight will look for this interface and subscribe to the PropertyChanged-event. As a developer you have to write code in your property setters to raise the event whenever some property is changed. This is boring and repetitive code to write, that often contains magic strings (property names) and can really clutter your ViewModels. Finding an elegant implementation of the INotifyPropertyChanged-interface has become one of the holy-grails of WPF and Silverlight developers.

An idea I had some time back where to use AOP-techniques and dynamic proxies to get INotifyPropertyChanged implemented automatically. With the recent beta release of Castle Dynamic Proxy 2.2 with official support for Silverlight, combined with Christmas holiday, I figured this would be a good time to take a stab at this problem.

After doing some research I found a couple implementations of INPC using AOP. In August 2008 Gian Mari Ricci published two blog posts about automatic implementation of INPC. The first one he used Reflection.Emit and dynamic code generation, the second was a much simpler implementation using Castle Dynamic Proxy.

In June Ray Houston published an interesting post on how they had implemented auto wiring of INPC as part of the Fluent Silverlight framework. Fluent Silverlight is an open source framework by Ray Houston and Gabriel Schenker that provides a fluent interface for configuring data binding in a strongly typed manner using C#. Their implementation of automatic wiring of INPC is based on Castle Dynamic Proxy, and is really simple and elegant. Instead of trying to reinvent the wheel I decided to re-implement the automatic INPC parts from Fluent Silverlight, and walk you through the code in this blog post. I do not want to take credit for Ray and Gabriel’s work, and must emphasize that this should be considered a walkthrough of their implementation.

The first part of the implementation is a new IAutoNotifyPropertyChanged interface that extends the INotifyPropertyChanged interface with one new method. This interface will be implemented for any ViewModel where we want automatic change notification. The interface serves as both a marker interface for the interceptor, as well as providing a method that the interceptor can call to raise the PropertyChanged-event.

IAutoNotifyPropertyChanged Code Example (code download attached)

To create a new ViewModel we simply implement the interface, and make any property we want change notification for as virtual. The properties need to be virtual so that the generated proxy class can override the property setter method and call the interceptor. The implementation of the interface can off course be moved down to a base class, but I have included it in this sample to make it clear what is required by the ViewModel for automatic change notification.

PersonViewModelCode

With a ViewModel implementing the IAutoNotifyPropertyChanged-interface in place we can now write an interceptor that will add change notification for the properties on the ViewModel. Interceptors are a concept from AOP that enables us to intercept method calls and add new behavior dynamically. This is helpful as we can move cross-cutting concerns out of the business logic. Typical use cases for AOP often include authentication, logging, exception handling and other technical concerns. By having these concerns implemented outside our class we can keep our business logic nice and clean. In our case we are going to apply some of these techniques to keep the ViewModel free from change notification code cluttering the class.

The interceptor is defined as a generic class that intercepts classes implementing the IAutoNotifyPropertyChanged-interface. The interceptor implements IInterceptor-interface which defines a method that will be called for every method invocation, providing us a hook to add addition behavior to the method call. Our interceptor will start by letting the original method call (the property setter) run before checking if we should raise change notification. If the property being set isn’t marked for exclusion we call the OnPropertyChanged method on the IAutoNotifyPropertyChanged-interface, passing in the property name as the parameter.

InterceptorCode

The code to determine if we should raise change notification starts by checking if the method being invoked is in fact a property setter. This is done by checking the IsSpecialName-property on the MethodInfo object, as well as checking that the name of the method starts with “set_“. The second step is to check if the property is marked with a DoNotNotifyChanges-attribute. This is a marker attribute that can be applied on properties to prevent automatic change notification. The third step is to check if the property being set is of type ICommand. A common pattern when creating ViewModels is to expose operations as Commands hanging of the ViewModel as properties. You do not need change notification for commands, so they are ignored by the interceptor.

ShouldSurpressCode

Now that we have our change notification interceptor the only thing missing is a way to create the proxy object. To do this we create a new proxy creator. The proxy creator has a generic method that creates proxied instances of any class implementing the IAutoNotifyPropertyChanged-interface.

ProxyCreatorCode

This diagram illustrates how the View calls the property setter on the proxied ViewModel. The property setter gets intercepted, and the interceptor lets the original setter execute before raising the PropertyChanged-event.

AutoINPCDiagram

Now that we got the proxy creator it is really straight forward to create an instance of our ViewModel that will have automatic change-notification. I have included the tests documenting the behavior of the automatic change notification interceptor. The tests documents change notification for simple properties, as well as exclusion of commands and properties marked with the DoNotNotifyChanges-attribute.

AutoINPCTestsCode

Summary

Using dynamic proxies for automatic change notification is a good way to keep your ViewModels nice and tidy as well as not having to hand-write tedious, repetitive change notification code. In my next blog post I will explore how we can integrate the change-notification interceptor with the Ninject IoC-container. By integrating the interceptor with an IoC-container we can have any ViewModel retrieved from the container support automatic change notification.

For more information about Castle Dynamic Proxy I would recommend Krzysztof Koźmic excellent 15-part tutorial.

The example code for this blog post requires Silverlight 3, and includes the latest beta of Castle Dynamic Proxy 2.2. The code is experimental, and not intended for production use.

Wednesday, December 23, 2009 5:02:10 AM (W. Europe Standard Time, UTC+01:00)
Hei Jonas, it's awesome to see you are blogging again! great article :) God Jul!
Wednesday, December 23, 2009 8:17:54 AM (W. Europe Standard Time, UTC+01:00)
You could use ProxyGenerationHook to narrow down the scope of the proxy.
Wednesday, December 23, 2009 9:34:52 AM (W. Europe Standard Time, UTC+01:00)
Nice article. But, ow about the scenario where you want the set-method of the ZipCode-property to fire the PropertyChanged-event for the City-property (which in some cases is inferred directly from the ZipCode)?
Thursday, December 24, 2009 4:16:57 AM (W. Europe Standard Time, UTC+01:00)
Jourdan: Thanks, it's great to be back! Warming up to 2010 - hope to get back into the blogging groove. God jul to you as well!

Krzystof: Thanks - I guess I should have read your complete tutorial first? ;) I've updated the code and moved the logic to determine weather or not to intercept a method into a ProxyGenerationHook. I described the change in a new blog post.

Anders: Good point! I guess you have two options - you can hand-write the ZipCode setter and raise change notification for the two others. The second options is described in a new blog post. I added a new attribute that lets you describe additional properties to raise change notification for.
Friday, December 25, 2009 11:11:17 PM (W. Europe Standard Time, UTC+01:00)
I don't like two things about this example:
1- the public method OnPropertyChanged.. .I think this method should be private or protected.
2- the partial implementation of the INotifyPropertyChanged. I think this is very wrong. If someone browse the class, can think that the class by itself implements INPC. I used to add the interface INPC at run time, with DP it is very easy.

You can catch the event handler registration. BTW we have taked this one step forward to make it work with nhibernate at unhaddins. And we have a full working example "The Chinook Media Manager". But If you want to see my interceptor, here is:

http://digg.com/u1Esum
Sunday, December 27, 2009 4:49:24 PM (W. Europe Standard Time, UTC+01:00)
It should be used in MVVM frameworks like http://www.codeplex.com/caliburn to stop doing non compile time checking code just like: NotifyOfPropertyChange("Contact").
Rodrigo Rodriguez
Wednesday, December 30, 2009 3:29:12 AM (W. Europe Standard Time, UTC+01:00)
Jose,

I agree with you. I think the class shouldn't implement the interface and it should be responsability of the interceptor. I'd just use a convention like the suffix ViewModel or classes on a particular namespace. Another approach would be based on the configuration in your IoC or probably even marking the class with an attribute.

The only problem with that approach would be if we wanted to explicitly Raise property change notifications. I still prefer it, because it keep things tidy, now our classes really don't have anything to do with this concern, which is the main purpose of AOP.
Wednesday, December 30, 2009 4:44:51 PM (W. Europe Standard Time, UTC+01:00)
Thanks for some great comments. Great that you guys are chipping in with ideas on how to implement this even better.

As for the partial implementation I don't think that is big issue as it's quite easy to agree upon a convention that INPC is implemented by a interceptor. I do think you should be able to raise change notification your self from the ViewModel, as there are cases where you want to do that. For instance setting a ZipCode might raise change notification for City and State.

This could be solved using an attribute like I did in my most recent blog post, but actually think implementing the setter by hand and raising the event is a cleaner approach.

I will see if I can make the OnPropertyChanged method protected, or skip it completely. Can I raise events from outside the class declaring the event without sub classing it? I can't make it private as Silverlight prevents private reflection.

Again - thanks for input guys!

Saturday, January 02, 2010 4:39:37 PM (W. Europe Standard Time, UTC+01:00)
When I did it I was using PostSharp, so it was all done at compile time and essentially the aspect was merged with the original class (no subclassing). In this case it won't work, you can only raise the event from the class declaring it, so you either have the OnPropertyChanged or move both the method and event to the interceptor. Another option would be to explicitly implement the interface, that way only classes doing an explicit cast would be able to see the method. To me that's a good enough way of hiding it.

In my experience I found few places where I need to explicitly raise property change notifications. With the DependsOn (or NotifyFor) trick you can avoid them. I still think that DependsOn makes more sense, even more than Raising the event explicitly in the setter of ZipCode. I know the attribute pushes the concern back to the ViewModel, but at least it does it in a declarative way.
Sunday, January 03, 2010 2:13:42 PM (W. Europe Standard Time, UTC+01:00)
I did some changes, it's working well and integrated with the IoC I added the DependsOnAttribute I mentioned before and made a couple of optimizations to reduce the usage of reflection.

Most changes are in this AutoNotifyPropertyChangedInterceptor class defined here http://snipt.org/qkno

The integration with the Ninject was just a matter of making your ProxyCreator an IProvider. I also overrode the GetDefaultBinding method in the Kernel to check if the type ends with ViewModel and implements the interface (which I might get rig of later) and simply create a new binding using the AutoNotifyPropertyChangedInterceptorProvider.

Thanks for the code. PostSharp proved to be too slow at compile time and I was looking for some alternative. I'm still a bit worried about the interceptor's performance at runtime, but I'll leave that for later. I'm thinking that a hybrid approach might be a last resource, on Release we use PostSharp on Debug we use Castle :s
Saturday, January 16, 2010 2:54:46 AM (W. Europe Standard Time, UTC+01:00)
I assume you've seen Justin Angels blog post about automatic INPC using both PostSharp as well as Mono.Cecil for MSIL weaving

Nice touch on perf. optimizations as well as turning it into a Ninject provider. Thanks for pointing me in the right direction. I started implementing the Provider my self, as well as your trick of overriding the GetBinding method. Btw, you say GetDefaultBinding - I couldn't find that method, but I do have a GetBinding. Which version are you using? I'm coding against the trunk of Ninject2 on GitHub.

The GetBindings signature looks like this IEnumerable<IBinding> GetBindings(Type service), and I couldn't figure out how to keep my Provider (and Proxy creator) strongly typed, and still support any type containing "ViewModel" in the name. I had to remove the generics from the provider and the interceptor. The interceptor now checks if the target implements IAutoPropertyChanged, and casts the target to the interface if possible.

If I register the provider in a module I can keep the generics:
Bind<ViewModel>().ToProvider<NinjectAutoNotifyProxyProvider<ViewModel>>();

Btw: did you implement support for injection of constructor parameters to the ViewModels in your provider? Or did you assume the Auto INPC VM's had a public empty constructor?

I've posted the code on http://snipt.org/qoZ if you wan't to have a quick look. Would love any tips on how to make the Provider and the Kernel cleaner.

Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview
<September 2010>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789