Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 08 | Comments: 18

filter by tags archive

Advance: Extending NHibernate Proxies

time to read 44 min | 8606 words

There was some interest in extending the way NHibernate deals with the entities, and I have just commited those changes into the trunk. Notice that since NHibernate 1.2.0 is at feature freeze right now, this will not be in 1.2.0 RTM, but at a later version.

At any rate, let us see how we can extend NHibernate so it would offer automatic implementation for INotifyPropertyChanged. Some caveats: It works only for entities that have lazy loading enabled (the default for 1.2.0) which were retreived from NHibernate.

You can see the full test here, but let me go through the implementation. First here is the test case:


public void CanImplementNotifyPropertyChanged()


       using (ISession s = OpenSession())


              Blog blog = new Blog("blah");

              Assert.IsFalse(blog is INotifyPropertyChanged);





       using (ISession s = OpenSession())


              Blog blog = (Blog)s.Load(typeof(Blog), 1);

              INotifyPropertyChanged propertyChanged = (INotifyPropertyChanged)blog;

              string propChanged = null;

              propertyChanged.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)


                     propChanged = e.PropertyName;



              blog.BlogName = "foo";

              Assert.AreEqual("BlogName", propChanged);



As you can see, when we create the entity manually, it does not implements INotifyPropertyChanged.  But when we load the object from NHibernate, not only does it implements INotifyProperyChanged, but it behaves correctly as well. They key is in extending the Proxy Factory that NHibernate uses for lazy loading.

We need to specify the proxy factory type that we would like to use:

protected override void BuildSessionFactory()





And now, let us see how the DataBindingProxyFactory works:

public class DataBindingProxyFactory : CastleProxyFactory


       public override INHibernateProxy GetProxy(object id, ISessionImplementor session)




                     CastleLazyInitializer initializer = new DataBindingInterceptor(_persistentClass, id,

                                _getIdentifierMethod, _setIdentifierMethod, session);


                     object generatedProxy = null;


                     ArrayList list = new ArrayList(_interfaces);


                     System.Type[] interfaces = (System.Type[])list.ToArray(typeof(System.Type));

                     if (IsClassProxy)


                           generatedProxy = _proxyGenerator.CreateClassProxy(_persistentClass, interfaces, initializer, false);




                           generatedProxy = _proxyGenerator.CreateProxy(interfaces, initializer, new object());



                     initializer._constructed = true;

                     return (INHibernateProxy)generatedProxy;


              catch (Exception e)


                     log.Error("Creating a proxy instance failed", e);

                     throw new HibernateException("Creating a proxy instance failed", e);




Here we did two things, We specify a different interceptor, which inherits from the default interceptor, that handles lazy loading, and we specify that the proxy that NHibernate returns should also implement INotifyPropertyChanged. Now, we need to see how the DataBindingInteceptor works:

public class DataBindingInterceptor : CastleLazyInitializer


       private PropertyChangedEventHandler subscribers = delegate { };


       public DataBindingInterceptor(System.Type persistentClass, object id, 
MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, ISessionImplementor session)

              : base(persistentClass, id, getIdentifierMethod, setIdentifierMethod, session)




       public override object Intercept(IInvocation invocation, params object[] args)


              if (invocation.Method.DeclaringType == typeof(INotifyPropertyChanged))


                     PropertyChangedEventHandler propertyChangedEventHandler = (PropertyChangedEventHandler)args[0];

                     if (invocation.Method.Name.StartsWith("add_"))


                           subscribers += propertyChangedEventHandler;




                           subscribers -= propertyChangedEventHandler;


                     return null;


              object result = base.Intercept(invocation, args);

              if (invocation.Method.Name.StartsWith("set_"))


                     subscribers(this, new PropertyChangedEventArgs(invocation.Method.Name.Substring(4)));


              return result;



We extend CastleLazyInitializer, which handles the usual lazy loading related logic for NHibernate, and when we get a method, we check to see if it a call to a method from the INotifyPRopertyChanged interface. If it is, we handle the add/remove of the event subscriber. But that is not the interesting part.

The interesting part is that after we let the method be processed normally (which is what the call to base.Intercept() does, we check to see if this is a property setter, and raise the appropriate event if it does.

The client code for this is very natural, and it took about 70 lines of code to add this functionality.


Andris Kurmis

Would it be hard to create some "generic" InterceptableProxyFactory, that is configurable from outside with a list of additional interfaces and a list of interceptors that implement methods like PreIntercept (basicly the code before "object result = base.Intercept(invocation, args);" and PostIntercept (after that)?

And another question (sorry -- I am not fluent with NHibernate internals) -- would your example work with "nosetter" or "field" strategies as well?



Ayende Rahien

Yes, it would be easy to create InterceptableProxyFactory.

And this example would work for other access strategies, because I am not trying to raise an event when NH is changing the value, I am raising the event whenever the property is changed by YOUR code.

Alessandro Cavalieri

Does this work with ActiveRecord too?

if yes, could you give me 2 rows of example on how can I use it?




i don't see that much of an advantage if not all instances of a certain class behave the same, i.e. implement INotifyPropertyChanged. if i need to distinguish between new an persistent objects what is the gain?

Ayende Rahien


Yes, it would.

The difference is that you would need to handle the ActiveRecordStarter event for models created and modify the Configuration object to register the new proxy factory, and then NH will handle everything else.

Comment preview

Comments have been closed on this topic.


  1. Concurrent max value - 7 hours from now
  2. Production postmortem: The case of the memory eater and high load - 3 days from now
  3. Production postmortem: The case of the lying configuration file - 4 days from now
  4. Production postmortem: The industry at large - 5 days from now
  5. The insidious cost of allocations - 6 days from now

And 5 more posts are pending...

There are posts all the way to Sep 10, 2015


  1. Find the bug (5):
    20 Apr 2011 - Why do I get a Null Reference Exception?
  2. Production postmortem (10):
    14 Aug 2015 - The case of the man in the middle
  3. What is new in RavenDB 3.5 (7):
    12 Aug 2015 - Monitoring support
  4. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats