Migrating from DynamicProxy to DynamicProxy2

Update II: I couldn't wait. I've installed the last Mono daily binary tarball and all the unit tests are passing now!. It works perfectly!

Update:The Mono implementation of GetMethodFromHandle for generics is already in the svn, so rather than write a conditional code I'll wait for the new binary release.

In the previous post about the BindableWrapper I was using DynamicProxy but I've realized that it doesn't work with generics. That is, if the class to which you are creating the proxy has generic methods or properties (public virtual List<T> MyList). Actually, it works on Mono but it doesn't on .Net, because the GetMethodFromHandle method has a different signature for generics and I didn't see that until I tested it on .Net. I guess it shouldn't work in Mono neither but it does.
The BindableWrapper hierarchy classes have been migrated to DynamicProxy2 and they are working fine now on .Net. However on Mono I'm getting a NotImplementedException with DP2 🙂 so I'm wondering if should I use conditional build to have both versions of DynamicProxy in order to have my classes working everywhere.These are the steps I made to migrate:

  1. Change the reference to Castle.DynamicProxy.dll, for Castle.DynamicProxy2.dll
  2. Add a reference to Castle.Core.dll
  3. Add this: using Castle.Core.Interceptor
  4. As the new parameters to CreateClassProxy, pass in IInterceptor[] and object[] arrays to prevent ambiguity problems
  5. Change the Intercept method signature in your implementation of IInterceptor:
    public override object Intercept(IInvocation invocation, params object[] args) - old
    public void Intercept(IInvocation invocation) - new
  6. Change the way to proceed on an interception:
    return base.Intercept(invocation, args); - old
    - new
  7. I was also inheriting from StandarInterceptor and now I'm just implementing the IInterceptor

It is straightforward to migrate but I'd advise to get the last daily binary build of the CastleProject in order to user DynamicProxy2. I don't like very much the release policy of the CastleProject because the last "stable version" was released the last year and the svn contains much more functionality and bugfixes. I rather would release versions more often using minor version numbers (i.e, 0.9.1...), making branches in the svn repository. So in my opinion the head of the svn is not unstable but the right decision if you choose Castle.

Bindable Business Objects

Update: Actually I'm changing this class a lot!. Check the svn head to see the current version.

Update: Refactoring makes things simpler

I am close to release the first API-stable version of my Boxerp framework which is only the client side part. The project has been changing a lot since it was created 3 years ago and it doesn't have a stable API but it is getting close at least for the client side. The new wiki in english will be published within weeks along with the binaries to downlad in the project site at berlios. Today I'm specially happy with the binding architecture as it is not very intrusive and flexible thanks to the Castle.DynamicProxy (AOP, Interception). The idea is to have some architecture to bind your business objects to the GUI (the widgets or controls) not having to change the objects themselves but rather wrapping them into another class. This class is strongly typed, extensible and implements to stacks so that you can easily undo or redo changes in the object properties:

BindableWrapper myBindable = new BindableWrapper(myBoInstance);

myBindable.Data.BusinessObj.PROPERTY_NAME = whatever


In addition, you not only may wrap the Business Object but also add some extra properties to the wrapper (i.e, your business object has some readonly property that you have to temporary read from the GUI), extending the classes (more docs in the wiki :-))

myOtherBindable.Data.SomeOtherProperty = whatever

I'll explain in detail the implementation of the class hierarchy but you can have a look at the base class implementation. I think it is one of the most complex classes I've ever written. The files are browsable in the svn and the images below:
abstractWrapper1.jpg abstractWrapper2.jpg abstractWrapper3.jpg

abstractWrapper4.jpg abstractWrapper5.jpg abstractWrapper6.jpg

I must say that the idea of cloning the IEnumerable in the cloneBindable method comes from my boss, Alex 😉

I see a few "problems":

  • The class is really difficult to maintain but it could be done with good documentation
  • The Business Objects needs to have properties declared as virtual and they must implement ICloneable making a deep copy of themselves.
  • If you define extra properties in the wrapper, you have to define them as virtual as well.
  • Performance: The wrapper is comprised of a nested class. Actually it is a proxy inside a nested proxy and the properties are copied using reflection on every change. I guess there will be no problems as long as you don't wrap huge collections, changing its items programmatically. This is intended for user interaction through the GUI only.

Moreover the classes need a refactoring and a strong unit testing, although you can check out unit tests from the repository.