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:
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.