Thursday 17 September 2009

Using Windsor to inject dependencies into your WCF services with WCF Integration Facility

IoC is pretty cool but sometimes you can’t use it straight out of the box with say something like WCF. Well now you can thanks to Ayende Rahien. Windsor contains a WCF Integration Facility that provides a WCF ServiceHostFactory which is used to create a service host for your service and injects any dependencies registered in Windsor. This is frighteningly simple to configure as you will see.

First define your interface and implement it in your service and expose your dependencies in your class constructor as you would normally.

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void SomeAction();
}
 
public class MyService : IMyService
{
    private readonly IDependancy dependancy;
 
    public PrintJobNotificationService(IDependancy dependancy)
    {
        this.dependancy = dependancy;
    }
 
    public void SomeAction()
    {
        //Do something intelligent
    }
}

If you are exposing the service as a web service using an svc file you will need to configure it to use the Windsor ServiceHostFactory. It is important to note that the name you use for the service should be the full type name less the assembly otherwise Windsor will not be able to find it. You can use a friendly string name but you will have to name your type when you register it with Windsor.

<%@
    ServiceHost Service="MyService"
    Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration"
%>

Otherwise you will need to instantiate it in code.

using(var serviceHost = new Castle.Facilities.WcfIntegration.DefaultServiceHostFactory().CreateServiceHost(typeof(WCFServices.IMyWCFService).AssemblyQualifiedName, new Uri[0]))
{
    serviceHost .Open();
}

Now you need to wire up Windsor with your service type and any dependencies as well as adding the WCF facility. You must also register your container with the Windsor’s service host factory which you can do via the static RegisterContainer on the DefaultServiceHostFactory.

container.AddFacility<WcfFacility>()
         .AddComponent<IDependancy, DependancyImplementation>()
         .Register(Component.For<IPrintJobNotificationService>().ImplementedBy<PrintJobNotificationService>());
 
DefaultServiceHostFactory.RegisterContainer(container.Kernel);

Finally you will need to configure your WCF components in the app/web.config. You can configure your endpoints and behaviours via Windsor but that is a topic for another post.

2 comments:

  1. Thanks for the post. I am using windsor castle version 3.1 so the above does not work anymore. Have you used 3.1 in this context? Thanks.

    ReplyDelete
  2. No I have not but the concept should be the same. One of the differences is that you should not need to register the kernel with the default service host factory anymore. What error are you getting?

    ReplyDelete