IoC

WCF + IoC = Unity.WCF

Keep service contracts clean
In my last post on implementing IErrorHandler for WCF, it was reasonably straight forwards to write a class that implements IErrorHandler; however to attach our errorhandler to the WCF service we had to apply it as an attribute of the contract.
I generally like to have the service contract in a seperate project from the actual service and have that contract service focus on just the contract. Adding an ErrorHandler attribute in there smells. Below is an alternative way of achieving this.

Make it clean
Ideally we should be attaching the errorhandler at the service level. Be great if we could just use an IoC mechanism to just inject our ErrorHandler into our service. Fortunately, we can!  The downside is that it’s a bit of a pain to code as you need to implement IInstanceProvider, add that through a custom behaviour and fiddle with the servcehost factory, which is a lot of work compared to just adding an attribute to our interface.

Don’t reinvent the wheel
Fortunately someone has done all this work for us and shared it on Nuget. It’s called Unity.WCF. It solves our problem perfectly for us. For a more detailed description of what it does visit http://www.devtrends.co.uk/blog/introducing-unity.wcf-providing-easy-ioc-integration-for-your-wcf-services. Aside from exposing a unity container for you it also allows you to supply implementations of IContractBehavior and IServiceBehavior, which is very hand as we’ll see.

What does it look like?

First install the package from Nuget, either through Visual studio or via this link. This will add a few files to your solution. The key file here is the WcfServiceFactory. If you have a look in here you will see just the one method

 protected override void ConfigureContainer(IUnityContainer container) 

. This method expose a unity container, allowing you to configure this container to inject classes as you want. Out of the box this looks like this

 protected override void ConfigureContainer(IUnityContainer container)
        {
			// register all your components with the container here
            // container
            //    .RegisterType<IService1, Service1>()
            //    .RegisterType(new HierarchicalLifetimeManager());
        }

In order to get our service to use this factory we simply need edit the markup in the .svc file – replace the codebehind call with a factory call.

Out of the box svc markup file:

<%@ ServiceHost Language="C#" Service="WcfService1.Service1" CodeBehind="Service1.svc.cs" %>

Change to:

<%@ ServiceHost Language="C#" Service="WcfService1.Service1" Factory="WcfService1.WcfServiceFactory" %>

Add our ErrorHandler

As we don’t want to apply our Errorhandler code as an attribute to the service contract, lets remove that, so our errorhandler now looks like:

public class ErrorHandler : IErrorHandler, IContractBehavior
{
... same code as before
}

Now we update the container in WcfFactory, to get it to inject our instance of an IContractBehaviour, and also setup the Service. This leaves our container looking like:

 protected override void ConfigureContainer(IUnityContainer container)
        {
        	container
        		.RegisterType<IService1, Service1>()
        		.RegisterType("MyErrorHandler");
        }

We need to give it a name, as unity.wcf uses container.ResolveAll which only returns named instances.

Use Unity to inject log4net

Finally we can tidy up our ErrorHandler from the last post by removing our “poor man’s dependency injection” and replace it with the slicker Unity container.
Previously our constructor looked like:

 public ErrorHandler()
            :this(LogManager.GetLogger("myassembly"))
        {}

        public MyErrorHandler(ILog logger)
        {
            _logger = logger;
        }

Enabling us to fully test the class by injecting an instance of ILog, or, the class would work without by firing up it’s own hard wired instance of log4net.

Now that we have a unity container we don’t need to have the case where the class isn’t injected as unity can manage this for us. So we just need the one constructor now

        public MyErrorHandler(ILog logger)
        {
            _logger = logger;
        }

Finally we update the container to look like

 protected override void ConfigureContainer(IUnityContainer container)
        {
        	container
        		.RegisterType()
        		.RegisterType("MyErrorHandler")
        		.RegisterInstance(LogManager.GetLogger("MyLogger"));
        }

Summary
That’s it. By adding unity.wcf to our WCF service we have, with minimal effort, enabled our WCF to use unity to wire up instances of our service contract, errorhandler and the errorHandler’s dependency on Ilog.

Advertisements