NHibernate & Static Proxies
I decided to take a look at what I would take to implement static proxies (via Post Sharp) in NHibernate. The following is my implementation log.
- 09:30 PM - Started to work on post sharp interceptors for NHibernate
- 09:35 PM - Needs to learn how I can implement additional interfaces with PostSharp.
- 10:00 PM - Implemented ICollection<T> wrapping for entities
- 10:35 PM - Proxy Factory Factory can now control proxy validation
- 11:15 PM - Modified NHibernate to accept static proxies
- 11:28 PM - Saving Works
- 11:35 PM - Deleting Works
- 11:50 PM - Rethought the whole approach and implemented this using method interception instead of field interception
- 11:58 PM - Access ID without loading from DB implemented
- 12:01 AM - Checking IsInitialized works
- 12:13 AM - After midnight and I am debugging interceptions issues.
- 12:15 AM - It is considered bad to kill the constructor, I feel.
- 12:16 AM - No one needs a constructor anyway
- 12:30 AM - Realized that I can't spell my own name
- 12:34 AM - Resorting to Console.Write debugging
- 12:40 AM - Wrote my own lazy initializer
- 12:42 AM - Realized that we can't handle lazy loading without forwarding to a second instance, need to see how we can capture references to the this parameter using PostSharp.
- 12;45 AM - I think I realized what went wrong
- 12:55 AM - Lazy loading for non virtual property references works!
- 12:57 AM - Constructors are back
- 12:59 AM - Lazy loading for calling non virtual methods works!
The first thing that I have to say is wow Post Sharp rocks! And I mean that as someone who is doing AOP for a long while, and has implemented some not insignificant parts of Castle.DynamicProxy. Leaving aside the amount of power that it gives you, PostSharp simplicity is simply amazing, wow!
The second is that while things are working, it is not even an alpha release. What we have right now is, literally, one evening's hacking.
What we have now is:
- Removed the requirement for virtual methods
- Removed the requirement for set to be an instance of Iesi.Collections.ISet<T>, now you can use ICollection<T> and HashSet<T>.
- Probably broken a lot of things
Consider this a proof of concept, as you can see, it takes time to implements those things, and currently I am doing it at the expense of time better spent sleeping. I started this because I wanted to get relax up from a 12 hours coding day.
If you have interest in this, please contribute to this by testing the code and seeing what breaks it. There are a bunch of TODO there that I would appreciate a second pair of eyes looking over.
You can get the code here: https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/branches/static-proxies
Note that you need to reset the project post build action to where you have PostSharp installed.
Oh, and I left a joke there, see if you can find it.
Comments
Wow, impressive!
How is the PostSharp compile time? It can slow down the compile quite significantly, it would be interesting to see how much for a 20-30 entities project.
How do you spell "Joke"? ...you're the Joker! :-)
Hehe, doing this to relax from a 12-hour coding day, that was funny :-)
Same approach could be followed to drop the need for default constructor and setters. Check for the default constructor and setters, if they are not in place add them as private and protected virtual respectively.
OTOH, post processing definitely affects compilation time badly and is a killer to use during development.
Sidar,
There is no requirement to have setters
So, you made a pre-execution attribute that un-proxies objects before the method call?
I am reading "11:58 PM - Access ID without loading from DB implemented", does that have anything to do with the painful Identity Insert Generator perchance?
Happy to see that you start the work announced in this post (about the use of post#)
groups.google.com/.../3e8660508c07e271&lnk=gst&...
Unhappy for don't see any discussion on NHibernate-development-list about this new work.
BTW to do it in trunk we must change ProxyFactoryFactory to delegate any responsibility about proxies to ProxyFactoryFactory implementors.
Not quite, it handle it the same way, by forwarding to implementation semantics.
The 11:58 thing is allowing you to do session.Load <customer(5).Id without hitting the DB
Comment preview