Adding Support for ISupportInitialize in NHibernate

The .NET ISupportInitialize interface is used when we want to support staged initialization for objects. Its BeginInit method is called when initialization is about to start and EndInit when it is finished.

If we want, it is easy to add support for it in NHibernate. An option would be:

  • BeginInit is called when the object is instantiated, like when NHibernate has loaded a record from the database and is about to hydrate the entity, and immediately after the Id property is set;
  • EndInit is called after all properties are set.

We do this by using a custom interceptor, like we have in the past. We start by writing a class that inherits from EmptyInterceptor, and implements the listener interface for the PostLoad event, IPostLoadEventListener:

   1: public sealed class SupportInitializeInterceptor : EmptyInterceptor, IPostLoadEventListener

   2: {

   3:     private ISession session = null;

   4:  

   5:     public override void SetSession(ISession session)

   6:     {

   7:         this.session = session;

   8:         base.SetSession(session);

   9:     }

  10:  

  11:     public override Object Instantiate(String clazz, EntityMode entityMode, Object id)

  12:     {

  13:         var listeners = (this.session.SessionFactory as SessionFactoryImpl).EventListeners;

  14:         var metadata = this.session.SessionFactory.GetClassMetadata(clazz);

  15:         var proxy = metadata.Instantiate(id, entityMode);

  16:         var initializable = proxy as ISupportInitialize;

  17:  

  18:         if (initializable != null)

  19:         {

  20:             initializable.BeginInit();

  21:         }

  22:  

  23:         if (listeners.PostLoadEventListeners.OfType<SupportInitializeInterceptor>().Any() == false)

  24:         {

  25:             listeners.PostLoadEventListeners = listeners.PostLoadEventListeners.Concat(new IPostLoadEventListener[] { this }).ToArray();

  26:         }

  27:  

  28:         return (proxy);

  29:     }

  30:  

  31:     #region IPostLoadEventListener Members

  32:  

  33:     void IPostLoadEventListener.OnPostLoad(PostLoadEvent @event)

  34:     {

  35:         var initializable = @event.Entity as ISupportInitialize;

  36:  

  37:         if (initializable != null)

  38:         {

  39:             initializable.EndInit();

  40:         }

  41:     }

  42:  

  43:     #endregion

  44: }

Then, before creating a session factory, we need to register it in the Configuration instance:

   1: var sessionFactory = cfg.SetInterceptor(new SupportInitializeInterceptor()).BuildSessionFactory();

Now, if your entity implements ISupportInitialize, NHibernate will automagically call its methods at the proper time. As simple as this! Winking smile

Published by

Ricardo Peres

Team Leader at Dixons Carphone. Microsoft MVP.

Leave a Reply

Your email address will not be published. Required fields are marked *