Ayende @ Rahien

It's a girl

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

Torkel
10/10/2008 07:29 AM by
Torkel

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.

Mickael
10/10/2008 08:10 AM by
Mickael

How do you spell "Joke"? ...you're the Joker! :-)

Philip L&#248;ventoft
10/10/2008 08:33 AM by
Philip Løventoft

Hehe, doing this to relax from a 12-hour coding day, that was funny :-)

Sidar Ok
10/10/2008 12:35 PM by
Sidar Ok

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.

Ayende Rahien
10/10/2008 01:13 PM by
Ayende Rahien

Sidar,

There is no requirement to have setters

pete w
10/10/2008 05:52 PM by
pete w

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?

Fabio Maulo
10/10/2008 06:41 PM by
Fabio Maulo

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.

Ayende Rahien
10/10/2008 06:45 PM by
Ayende Rahien

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

Comments have been closed on this topic.