There has been lots of talk in the Silverlight community about what is the best way to implement the INotifyPropertyChanged interface. During Christmas I blogged about how you can use dynamic proxies to get INPC implemented automatically. Since then both Einar Ingebrigtsen and Justin Angel have blogged about an interesting approach to INPC using MSIL weaving. I really recommend checking out Justin’s post, as he covers some of the pros and cons of different INPC implementations, as well as purposing an elegant solution using post-build MSIL weaving.
One of the things Justin mentions as a drawback of the dynamic proxy approach is that you cannot simply new up your ViewModel directly and get change notification automatically. You have to explicitly create the ViewModel instance through a proxy creator. Einar also mentioned that he had a hard time finding a way to integrate the proxy creator with an IoC container.
When I write code I’m always careful about where I instantiate my objects, and lately all projects I’ve worked on have used some sort of IoC container. Having an IoC container gives you a single place in your code base to create- and register objects. If the dynamic proxy implementation of automatic INPC is going to be useful it has to be as simple requesting a ViewModel instance from the IoC container. In this blog post I’m going to show how you can combine automatic INPC using dynamic proxy with the Ninject IoC container.
If you have read my blog you may have noticed I got a soft spot for Ninject. I mean, who cannot love a framework whose name, graphic profile and code examples are all about Ninjas? When I first set out to integrate my automatic INPC interceptor with Ninject I wasn’t quite sure where to start. Ninject 1.0 had AOP concepts built in, but in 2.0 (which are under development) this has been moved out of the core and into a separate interception extension module. This is part of the new modular design of Ninject 2.0. Features you may not need all the time are moved out to separate extensions, leaving the core really small and simple (~90kb).
My first plan was to use the Ninject interception extension. The extension uses the LinFu framework for dynamic proxies, and I wasn’t sure how to get my Castle Dynamic Proxy based implementation to work directly. I later got contacted by Ian Davis, the owner of the interception-extension project. He asked if I needed some help getting automatic INPC working with Ninject. After some back-and-forth on Twitter Ian had an implementation of automatic INPC added to the Ninject.Extension.Interception project. The code is commited to the trunk, and is available on github if you want to check it out. Ian’s implementation is probably worth a blog post on its own.
A comment from Miguel Madero pointed me in the right direction to get my interceptor working with Ninject. Miguel had integrated it himself by implementing the interceptor as a Ninject Provider. Ninject lets you register types against providers which let you write code that creates the instance when the type is requested from the container. The interface is really simple, having one Create-method. In this method you have to create the instance being requested.
The implementation for the automatic INPC provider is fairly simply. It finds the largest constructor of the ViewModel being requested, creates instances of all constructor parameters, before calling the dynamic proxy creator I implemented in my previous two blog posts.
In Ninject all configuration is done through code using an internal DSL. You configure the container by creating module classes specifying the bindings of the different types you want to be able to create. In this example I have a simple logging service (to demonstrate constructor injection combined with automatic INPC) as well as a simple ViewModel. The ViewModel is bound to the provider, which will call the proxy creator when the ViewModel is requested.
This unit tests shows how to request an instance of the ViewModel from the container. When the Name-property is set the ViewModel will log the action to the fake logger which was injected into the ViewModel constructor.
Having to register every single ViewModel against the provider is tedious and repetitive. Miguel Madero also suggested that you can override the GetBinding method of the Ninject StandardKernel and use convention over configuration. By overriding the GetBinding method we can check if the type being requested is a ViewModel, and if it is we can create a binding on the fly tying the ViewModel type against the automatic INPC provider.
The implementation of the AutoNotifyKernel is really simple. It checks if the name of the type being requested contains “ViewModel” and implements the IAutoNotifyPropertyChanged interface. If it does we create a binding for the type.
Having a convention based approach in place we do not have to manually register every single ViewModel.
Some of this code might seem complicated, but I really wanted to cover the details of how to integrate it with Ninject, as similar approaches probably work for other containers. Once you got a framework for automatic INPC in place the usage becomes really simple. In the example application for automatic INPC the code needed to implement the ViewModel, configure the container and tie the ViewModel to the View looks something like this:
It’s funny how such a simple interface can trigger so many different implementations. I hope you found my blog post on combining a dynamic proxy approach with an IoC container useful. It will be interesting to see which approach emerges as the most used, and which frameworks that will provide implementations of the different techniques.