WCF, Unity and NHibernate - First Findings

This blog post is to continue on the one I wrote a few days ago about a new architecture for a WCF project we're trying out.

My colleague Tomas and I sat down the whole day yesterday and dug into the topic and came out with a first rough code architecture that seems to work. Both of us knows WCF pretty well, but we're new to Unity and NHibernate so this baby has to be tested thoroughly :)

First, thanks to Ray Henry, who wrote a couple of nice posts about how to use Unity with WCF. That information was superb. Basically we're using a custom Service Host Factory which we point at from the .svc markup file:

<%@ ServiceHost Language="C#" Debug="true" Service="WcfUnity.TestService" 
CodeBehind="TestService.svc.cs" Factory="WcfUnity.UnityService.UnityServiceHostFactory" %>

The UnityServiceHostFactory is where we currently registers the types that is to be injected into our code. Right now we're doing it in code, and we're only working with 2 classes; the NHibernate Repository and the NHibernate Session Manager (which is a singleton):

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

        {

            var unity = new UnityContainer()

            .RegisterType<IRepository, NHibernateRepository>()

            .RegisterType<INHibernateSessionManager, NHibernateSessionManager>(new ContainerControlledLifetimeManager());

 

            var host = new UnityServiceHost(serviceType, baseAddresses)

                           {

                               Container = unity

                           };

 

            return host;

        }

The Session Manager is responsible for setting up the NHibernate Session Factory which is expensive and you only want to do that once. In short - the factory creates a new WCF service host which creates a service behavior which is called each time before a requested service class is instantiated. To be able to resolve and inject our registered classes, the behavior uses a specific instance provider which does Resolve as part of its GetInstance() method. It's all described in detail by Ray in his post, so go check it out. I've not seen a better example of Unity + WCF out there yet and from what I can see in our, so far limited, testing it works well.

When that plumbing is done (some 4 small classes, that's all), we got a very clean service implementation class with the IRepository injected into it:

    public class TestService : ITestService

    {

        private readonly IRepository _repository;

 

        public TestService(IRepository repository)

        {

            _repository = repository;

        }

 

        // ITestService members goes here...

 

    }

 

You don't see any trace if a container, just the way it should be. Currently we're looking at our Repository interface and a decent syntax for a Unit Of Work. I'm fond of the lambda style of coding, and I'm playing something like this now:

            var response = new GetPersonResponse();

            _repository.UnitOfWork(() =>

               {

                   var person = _repository.Find<Person>(request.Id);

                   ret.Person = person;

               });

            return response;

Or for a transaction:

            var response = new AddPersonResponse();

            _repository.TransactionalUnitOfWork(() =>

                {

                    _repository.Save(request.Person);

                    response.Person = _repository.Find<Person>(request.Person.Id);

                });

            return response;

The TransactionalUnitOfWork method would do things like:

        public void TransactionalUnitOfWork(Action action)

        {

            _session = sessionManager.GetSession();

            var transaction = _session.BeginTransaction();

            try

            {

                action();

                transaction.Commit();

            }

            catch (Exception)

            {

 

                transaction.Rollback();

                throw;

            }

            finally

            {

                transaction.Dispose();

                _session.Close();

            }

        }

The "problem" is that the UoW shouldn't go into the repository implementation, it's wrong but I'm only trying things out here. I might as well wrap the opening and closing of a NH Session and transaction within an IDisposable and call it my UoW as many others have done before me, but I kind of like this. Have to think about not letting things that should stay inside the repository "leak" out... At this moment we're only playing around with things :)

We also need to encapsulate and inject business rules in a good way as we will host the services at more than one customer with different rules. MEF could be an option actually... more on that later :)

No Comments