Latest Tweet:
  • Loading...

Yesterday I published a post showing how we can use AOP and Castle Dynamic Proxy to get automatic change notification for ViewModels by intercepting property setters. One of the comments I got was from Krzysztof Koźmic who suggested that I should use ProxyGenerationHook to narrow down the scope of the proxy.

By implementing the IProxyGenerationHook we get to choose which methods to intercept. In my original implementation this logic was handled by the interceptor itself. The interceptor would check that the method being intercepted was indeed a property setter, that it was not of type ICommand, and that it was not marked for exclusion. By implementing a ProxyGenerationHook I could move all this code into a separate class, making my interceptor much cleaner. The ShouldInterceptMethod implementation of the ProxyGenerationHook now looks like this:

ProxyGenerationHookCode

I also got a good question from Anders Knutsen asking how to handle change notification for properties depending on another property. A typical scenario for a ViewModel might be to have a ZipCode-property with both setter and getter, and City and State properties with only getters. When you set the ZipCode you raise change notification for ZipCode, City and State. In the City- and State-getter you look up the values based on the ZipCode. This means that you must be able to raise multiple change notifications in a single setter.

I solved this by adding a new NotifyChangesFor-attribute that you can decorate properties with to trigger change notification for additional dependent properties.

NotifyChangeForAttributeCode

I have also updated the tests to document this behavior.

NotifiyChangesForTestCode

The sample code has been updated with the new ProxyGenerationHook and the new NotifyChangesFor-attribute.

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.

<September 2010>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789