NHibernate interceptor magic tricks, pt. 3

Posted on February 14, 2011 · 3 mins read · tagged with: #

The very last meeting with IInterceptor was ended by description of IInterceptor.GetEntityName(object entity); method. It’s time to step into the kingdom of almighty DI and IoC and learn how to combine it with NHibernate.

Instantiate me, now!

Imagine that you have a dependency passed as your entity constructor. Or you have some methods or properties which should be called immediately after one entity construction. (It’s out of the scope of this blog whether injection dependencies in your entities is good or bad. You can ask Google and check whether one or another solution fits for you.) One of the proposals of having an entity class with a non default constructor is providing a custom IByteCodeProvider. You can find this solution in here but I would recommend another one, if only entity creation bothers you (the mentioned IByteCodeProvider initializes much more NHibernate elements than you can imagine). The second approach is to use IInterceptor.Instantiate(string entityName, EntityMode entityMode, object id) method. As it was shown by Ayende in his MSDN article, the code should look like (I use in the example Unity container interface):

public class DependencyInjectionInterceptor : EmptyInterceptor
{
    private readonly IUnityContainer _container;
    private ISession _session;

    public DependencyInjectionInterceptor (IUnityContainer container)
    {
        _container = container;
    }

    public void SetSession(ISession session)
    {
        _session = session;
    }

    public over
        ride object Instantiate(string clazz, EntityMode entityMode, object id)
    {
        if(entityMode == EntityMode.Poco)
        {
            var type = Type.GetType(clazz);
            if (type != null)
            {
               var instance = _container.Resolve(type);
               var md = _session.SessionFactory.GetClassMetadata(clazz);
               md.SetIdentifier(instance, id, entityMode);
               return instance;
            }
        }
        return base.Instantiate(clazz, entityMode, id);
  }
}

You can consider passing the ISessionFactory in the constructor as dependency, but as I tend to use IInterceptor one per session, I simply use the SetSession method and further, the SessionFactory property.

That would be all about a simple case of dependency injection with NHibernate (creating only your entities). It seems that there will be a few posts more about IInterceptor stuff ;-)


Comments

Do you happen to have a sample of your implementation of this? I have been looking for something like this for a while but can't seem to get NHibernate to use the injector to satisfy the POCO's dependencies.

by JH at 2011-02-15 14:20:27 +0000

If you just could wait a few days, I would present a full-blown sample of an interceptor implementing all the features I mentioned. It'll take a while to gather it in one place, but yes - I do have an example because I'm currently using it (the dependency stuff) in a few of my projects :)

by scooletz at 2011-02-15 22:09:57 +0000

I figured out my issue. I needed to register the type with the dependency in my IoC container as well as the dependency itself.

by JH at 2011-02-22 21:44:01 +0000

If you do not scan all of you assemblies and register everything automatically, then you have to do it explicitly. Nice you've got it running!

by scooletz at 2011-02-23 09:30:25 +0000