Blog

  • Home /
  • Blog /
  • Integrating Castle Windsor and NHibernate with WCF - Throwing the WCF facility and some Rhino Tools in the mix

Integrating Castle Windsor and NHibernate with WCF - Throwing the WCF facility and some Rhino Tools in the mix

July 14, 2008

A while ago, I wrote this post about how to integrate Castle Windsor and NHibernate with WCF. Last weekend, I used the WCF integration facility of Castle Windsor to accomplish pretty much the same thing, but with less code. We all want that, now don't we?

As a first step, I created a class that implements the ICallContextInitializer.

public class UnitOfWorkContext : ICallContextInitializer
{
    private IUnitOfWork _unitOfWork;

    public Object BeforeInvoke(InstanceContext instanceContext, 
                               IClientChannel channel, 
                               Message message)
    {
        _unitOfWork = UnitOfWork.Start();
        return null;
    }

    public void AfterInvoke(Object correlationState)
    {
        if(_unitOfWork != null)
        {
            _unitOfWork.Dispose();
            _unitOfWork = null;
        }
    }
}

Notice that I'm not using the SessionFactory and Session classes of NHibernate directly. Instead, I'm using the UnitOfWork classes of Ayende's most excellent Rhino Tools library.

Next an implementation of the IServiceBehavior interface needs to be created in order to apply the UnitOfWork context to the service operations.

public class UnitOfWorkBehavior : IServiceBehavior
{
    public void ApplyDispatchBehavior(
            ServiceDescription serviceDescription, 
            ServiceHostBase serviceHostBase)
    {
        foreach(var channelDispatcher in 
                serviceHostBase.ChannelDispatchers)
        {
            var channelDispatcher = cdb as ChannelDispatcher;
            if(null != channelDispatcher)
            {
                foreach(var endpointDispatcher in 
                        channelDispatcher.Endpoints)
                {
                    foreach(var dispatchOperation in 
                    endpointDispatcher.DispatchRuntime.Operations)
                    {
                        dispatchOperation.CallContextInitializers
                            .Add(new UnitOfWorkContext());
                    }     
                }
            }
        }
    }

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

    public void Validate(ServiceDescription serviceDescription, 
                         ServiceHostBase serviceHostBase) 
    { }    
}

So far, nothing really new actually. In my previous post, I needed to create a custom ServiceHost and ServiceHostFactory class. This is now taken care of by the WCF integration facility of Castle Windsor. I'm using IIS hosting, so I need to add the DefaultServiceHostFactory of the facility to the ServiceHost file:

<%@ ServiceHost Language="C#" 
                Debug="true" 
                Service="WindsorService.MyWindsorService" 
                Factory="Castle.Facilities.WcfIntegration.
                     DefaultServiceHostFactory, 
                     Castle.Facilities.WcfIntegration"
                CodeBehind="MyWindsorService.svc.cs" %>

Next, we need to add the facility and the service behavior to the Windsor configuration file:

<facilities>
    <facility id="wcf"
              type="Castle.Facilities.WcfIntegration.WcfFacility,
                    Castle.Facilities.WcfIntegration" />
</facilities>
<components>
    ...
    <!-- Service behavior -->
    <component id="UnitOfWorkBehavior"
         type="WindsorService.Wcf.UnitOfWorkBehavior, 
                   WindsorService"/>
    ...
</components>

We're almost done. As I also mentioned in my previous post, I have this wrapper class for Castle Windsor named DependencyContainer. The last thing we need to do is register the Windsor container for the WCF integration facility:

public DependencyContainer()
{
    _windsorContainer = new WindsorContainer(
        new XmlInterpreter());
    
    // For Windsor WCF facility
    DefaultServiceHostFactory
        .RegisterContainer(_windsorContainer.Kernel);

    // For Rhino Commons
    IoC.Initialize(_windsorContainer);
}

An instance of the DependencyContainer is now created in the Global.ApplicationStart method:

public class Global : HttpApplication
{
    private IDependencyContainer _dependencyContainer;

    protected void Application_Start(object sender, EventArgs e)
    {
        _dependencyContainer = new DependencyContainer();
    }

    protected void Application_End(object sender, EventArgs e)
    {
        _dependencyContainer.Dispose();
        _dependencyContainer = null;
    }
}

Voila, no rocket science there either. We're done. What are we exactly gaining here? The biggest benefit is that we can now add WCF behaviors for other concerns, like exception handling, logging, transactions, etc. by just adding them to the Windsor configuration file.

Now, to round off this post I want to show the usage of the Repository library that can also be found in the Rhino Tools Library. The following needs to be added to the Windsor configuration file:

public class Global : HttpApplication
{
    private IDependencyContainer _dependencyContainer;

    protected void Application_Start(object sender, EventArgs e)
    {
        _dependencyContainer = new DependencyContainer();
    }

    protected void Application_End(object sender, EventArgs e)
    {
        _dependencyContainer.Dispose();
        _dependencyContainer = null;
    }
}

Now we can use the Repository class like so:

public IEnumerable<Customer> GetAll()
{
    return Repository<Customer>.FindAll(
         DetachedCriteria.For(typeof(Customer))
        .SetFetchMode("Orders", FetchMode.Eager));
}

public Customer GetFor(String code)
{
    return Repository<Customer>.Get(code);
}

These repositories even have support for fetching strategies, which is actually pretty neat.

I'm happy to hear some feedback on this.

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