Inversion of control and WCF

Lots of people like to use in inversion of control container, usually shortened to IOC, to inject dependencies into classes. The are lots of reasons for doing so but in the end they mostly boil down to separation of concern which makes thing more modular and thereby easier to reuse and unit test.

When you start doing so manually injecting dependencies into a types constructor is easy enough but after a while this tends to become tedious and getting an IOC container to do this for you is a lot easier. The problem is that you don’t always control the object creation and therefor are not always able to insert dependencies into the constructor, even when using an IOC container. One of these case is with an WCF service where WCF takes care of the service lifetime and creates new objects as needed.

Fortunately WCF is designed in a very modular fashion itself and allows you to replace almost everything in the box. Basically WCF uses an implementation of the IInstanceProvider to create new service objects. Now you can go and implement IInstanceProvider yourself and hook that in but why bother if there are existing IOC containers that will do the job for you.

 

Using Ninject with WCF

There are plenty of IOC containers to choose from but I like Ninject and that is available through NuGet so that is what I will use for this example. If you prefer another IOC container its quite likely that it has a similar capability and if not you can use IInstanceProvider to add it yourself.

 

I have start by creating a very standard WCF service using the WCF Service Application template. This gives us two methods, the GetData() and GetDataUsingDataContract(). Lets use the first to call an repository to get some data. so the first thing I to factor out the implementation of of the GetData().

public class Service1 : IService1


{


    private IRepository _repo;


 


    public Service1(IRepository repo)


    {


        _repo = repo;


    }


    public string GetData(int value)


    {


        return _repo.GetData(value);


    }


}

And the actual GetData() implementation in the Repository class.

public interface IRepository


{


    string GetData(int value);


}


 


public class Repository : IRepository


{


    public string GetData(int value)


    {


        return string.Format("You entered: {0} using {1}", value, GetType().FullName);


    }


}

Simple enough right? Normally a repository is quite a bit more complex, it usually does database access or similar things, but to demonstrate the WCF integration that is good enough.

 

If you try to use the WCF service now you will see the following error message:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

Makes sense because the standard IInstanceProvider implementation only works with default constructors and we are expecting the IRepository in our constructor.

 

Adding Ninject

There is a WCF extension for Ninject that will do exactly this for us. Add a Library Package Reference to the project and search for “Ninject.Extensions.Wcf”. You can also just search for Ninject and it will show up on the first page. Add this “Ninject.Extensions.Wcf” package and it will automatically add Ninject as a dependency to the project.

image

Next we need to create a class deriving from NinjectModule that will define your dependencies. In the Load() method we tell Ninject that every time we need an IRepository it should provide us with an Repository object.

public class MyNinjectModule : NinjectModule


{


    public override void Load()


    {


        Bind<IResolutionRoot>().ToConstant(Kernel);


        Bind<ServiceHost>().To<NinjectServiceHost>();


        Bind<IRepository>().To<Repository>();


    }


}

 

The IResolutionRoot isn’t really required, but a very useful default to add to the module.

Wiring things up requires us to add a Global.asax. t would be nice if the package did the basic work for us because there is no documentation with the package Sad smile but fortunately doing so isn’t hard, just a one line in the Application_Start() method.

protected void Application_Start(object sender, EventArgs e)


{


    KernelContainer.Kernel = new StandardKernel(new MyNinjectModule());


}

 

This leaves just one change to make and that is to specify the service factory what will wire up the required WCF behavior and that is added to the Service1.svc file.

<%@ ServiceHost Language="C#" 


                Debug="true" 


                Service="WcfService7.Service1" 


                CodeBehind="Service1.svc.cs" 


                Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"%>






With this last piece in place our WCF services uses Ninject as an IOC container and runs just fine.






Enjoy!



[f1]
[f2]

One thought on “Inversion of control and WCF

  1. Broken in ninject 2.2:

    The KernelContainer is no longer available to tell ninject the module with mappings to use.

    I must be using the wrong search terms “ninject wcf mapping” :-(

    This (mapping injections) is the first (only) point of using an IOC container in the first place, so it frustrates me that I can’t figure it out…

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>