Today I encountered a pretty basic scenario that Unity can’t support out of the box: one NHibernate ISession per HttpContext.

The problem is that ISessions are provided by a factory method NHibernateHelper.OpenSession(), and I need to store them in a custom HttpContextLifetimeManager. Unity won’t let me use the two together because no RegisterFactory() overload allows you to specify a LifetimeManager.

Rupert Benbrook has posted a solution to this problem that overrides part of the Unity build-up pipeline (and even goes as far as emitting op codes directly). For simple applications, however, a plain extension method might suffice:

public static IStaticFactoryConfiguration RegisterFactory<T>(
    this StaticFactoryExtension extension,
    FactoryDelegate factoryMethod, LifetimeManager lifetimeManager)
{
    FactoryDelegate wrappedFactoryMethod = delegate
    {
        LifetimeManager manager = lifetimeManager;
        FactoryDelegate method = factoryMethod;
        IUnityContainer container = extension.Container;

        object o = manager.GetValue();
        if (o == null)
        {
            o = factoryMethod(container);
            manager.SetValue(o);
        }
        return o;
    };

    return extension.RegisterFactory<T>(wrappedFactoryMethod);
}

This simply wraps the real factory method in a closure that checks a LifetimeFactory first. I can then do:

container.Configure<StaticFactoryExtension>()
    .RegisterFactory<ISession>((c) => NHibernateHelper.OpenSession(),
    new HttpContextLifetimeManager<ISession>());

This seems to work pretty well.

May 26th, 2009 | 1 Comment

I found an interesting problem this morning when my ASP.NET MVC application mysteriously broke after adding an HttpModule in the web.config. Here’s the problem code:

public class MvcApplication : HttpApplication, IUnityContainerAccessor
{
    IUnityContainer container;

    public IUnityContainer Container
    {
        get { return container; }
    }

    public void Application_Start()
    {
        this.container = new UnityContainer();

        // this.container.RegisterTypes etc
    }

The container was being configured fine in Application_Start, but then UnityControllerFactory would throw “The container seems to be unavailable in your HttpApplication subclass” exceptions every time you tried to load a page — this.container was somehow null again.

After doing a little digging and finding this article where someone had the same problem with Winsdor, it seems ASP.NET will create multiple HttpApplication instances when parallel requests are received. However, Application_Start only gets called once, so anything you would like to share between multiple instances (e.g. your IoC container) must be static:

public class MvcApplication : HttpApplication, IUnityContainerAccessor
{
    static IUnityContainer container; // good

    IUnityContainer container; // bad, not shared between HttpApplication instances

    public IUnityContainer Container
    {
        get { return container; }
    }
April 17th, 2009 | 2 Comments