Blog

  • Home /
  • Blog /
  • Integrating Castle Windsor and NHibernate with WCF

Integrating Castle Windsor and NHibernate with WCF

May 18, 2008

Up until now, we were using the NHibernate facility of Castle Windsor for managing our NHibernate sessions in WCF. But, we want to have a session-per-request approach as one would use when integrating NHibernate with a regular web application.

Yesterday I did a small spike to figure out how this should work. It turned out to be pretty easy. I used this excellent blog post written by Oran Dennison as my guide.

First I created a class that implemented the IServiceBehavior interface.

public class DIServiceBehavior : IServiceBehavior
{
    private readonly ISessionFactory _sessionFactory;

    public DIServiceBehavior()
    {
        _sessionFactory = new Configuration()
            .Configure()
            .BuildSessionFactory();

        XmlConfigurator.Configure();    // Log4Net
    }

    public void ApplyDispatchBehavior(
             ServiceDescription serviceDescription, 
             ServiceHostBase serviceHostBase)
    {
        foreach(ChannelDispatcherBase cdb in 
                serviceHostBase.ChannelDispatchers)
        {
            ChannelDispatcher cd = cdb as ChannelDispatcher;
            if(cd != null)
            {
                foreach(EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider =
                        new DIInstanceProvider
                            (serviceDescription.ServiceType,
                              _sessionFactory);
                }
            }
        }
    }

    public void AddBindingParameters(
                ServiceDescription serviceDescription, 
                ServiceHostBase serviceHostBase,
                Collection<ServiceEndpoint> endpoints, 
                BindingParameterCollection bindingParameters) 
    { }
    
    public void Validate(ServiceDescription serviceDescription, 
                         ServiceHostBase serviceHostBase) 
    { }
}

The SessionFactory is created in the constructor because the ApplyDispatchBehaviour method can be called multiple times (for each endpoint).

The next step is to create an instance provider by creating a class that implements the IInstanceProvider:

public class DIInstanceProvider : IInstanceProvider
{
    private const String NHibernateSessionKey = 
        "NHibernate.Session";

    private readonly Type _serviceType;
    private IDependencyContainer _dependencyContainer;
    private readonly ISessionFactory _sessionFactory;
    private ISession _session;

    public DIInstanceProvider(Type serviceType,
                               ISessionFactory sessionFactory)
    {
        Debug.Assert(null != serviceType, 
                     "null != serviceType");
        _serviceType = serviceType;

        Debug.Assert(null != sessionFactory, 
                     "null = sessionFactory");
        _sessionFactory = sessionFactory;
    }

    public Object GetInstance(InstanceContext instanceContext)
    {
        return GetInstance(instanceContext, null);
    }

    public Object GetInstance(InstanceContext instanceContext, 
                                Message message)
    {
        _dependencyContainer = new DependencyContainer();

        _session = _sessionFactory.OpenSession();
        _dependencyContainer
          .AddComponentInstance(NHibernateSessionKey, _session);

        return _dependencyContainer.Resolve(_serviceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, 
                                 Object instance)
    {
        if(null != _session)
        {
            _session.Close();
            _session = null;
        }

        if(null != _dependencyContainer)
        {
            _dependencyContainer.Dispose();
            _dependencyContainer = null;
        }
    }
}

I created a wrapper class around for Castle Windsor named DependencyContainer.  The GetInstance method opens a new session using the SessionFactory object we instantiated in the service behavior class. The session object is then registered with Castle Windsor. We can now implement our repositories like this:

public class SomeAggregateRepository
{
    private ISession _session;

    public SomeAggregateRepository(ISession session)
    {
        _session = session;
    }
    
    public SomeAggregate Get(Int64 id) 
    {
        return _session.Get<SomeAggregate>(id);
    }
}

When our service operation has been executed, the NHibernate is released by the ReleaseInstance method. Finishing our example, we need to implement a custom ServiceHost and a ServiceHostFactory:

public class DIServiceHost : ServiceHost
{
    public DependencyInjectionServiceHost() 
        : base() 
    { }
    
    public DIServiceHost(Type serviceType, 
                         params Uri[] baseAddresses) 
        : base(serviceType, baseAddresses) 
    { }

    protected override void OnOpening()
    {
        Description.Behaviors.Add(new DIServiceBehavior());
        base.OnOpening();
    }
}

public class DIServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(
            Type serviceType, Uri[] baseAddresses)
    {
        return new DIServiceHost(serviceType, baseAddresses);
    }
}

The custom ServiceHostFactory class can now be used in the ServiceHost file required when doing IIS hosting:

<%@ ServiceHost Language="C#" 
                Debug="true" 
                Service="WindsorService.MyWindsorService" 
                Factory="WindsorService.DIServiceHostFactory"
                CodeBehind="MyWindsorService.svc.cs" %>

There is also another way for achieving this that I will be investigating the next week or so using the WCF Integration Facility for Castle Windsor. For some reason it is not available in the current release of the Castle stack so I have to grab it from the trunk.

If you have any thoughts, improvements or suggestions I'm glad to hear them from you, my dear reader. It's the only way I'll ever learn :-).

Till next time.

If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at infonull@nullprincipal-itnull.be.

Profile picture of Jan Van Ryswyck

Jan Van Ryswyck

Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Comments

About

Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.

Contact information

(+32) 496 38 00 82

infonull@nullprincipal-itnull.be