Home > C#, IoC, Ninject, WCF > Using an IoC container to create WCF service instances

Using an IoC container to create WCF service instances

Introduction

Using dependency injection and an IoC container increase the robustness of an application. Dependency injection is a design pattern that decouples behavior from dependency resolution. Thus making it easier to replace the actual implementation of components by mocked implementations during unit tests. IoC containers are frameworks that help you resolve dependencies for your .Net classes. Various implementations exist: Microsoft Unity, Ninject, Spring.Net, …

By default WCF requires that service implementation classes have a parameterless constructor. The sole exception are self hosted singleton services. In that case, you could also pass the required instance to the constructor of your ServiceHost class.

Luckily for us, WCF is very extensible and it allows us to change the component that is responsible for creating service instances. This component is called the instance provider and implements an interface called IInstanceProvider. In this article, I will show you how to create a new implementation that uses Ninject, but you could also use the IoC container of preference.

Getting Ninject

First we need to add Ninject to our project. Because NuGet is so popular these days in the Microsoft world, lets use it. So right click on References in Visual Studio and chose “Add Library Package Reference” and then search for Ninject.

AddLibraryPackageReference

When you click “install”, NuGet will download and add all the required assemblies of Ninject to the Visual Studio project. It will not install them in the GAC.

Creating the InstanceProvider

When you create a custom InstanceProvider, all you have to do is implement the interface IInstanceProvider. The required code to use an IoC container is very straightforward. We pass the Ninject kernel and the service type to the instance provider constructor and use the Ninject kernel to create instances of the service when required.

public class NinjectInstanceProvider : IInstanceProvider
{
    private Type serviceType;
    private IKernel kernel;

    public NinjectInstanceProvider(IKernel kernel, Type serviceType)
    {
        this.kernel = kernel;
        this.serviceType = serviceType;
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return this.GetInstance(instanceContext, null);
    }

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        // Create the instance with your IoC container of choice, here I use Ninject.
        return kernel.Get(this.serviceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
    }
}

Hooking into the WCF pipeline

Now that we have created our custom instance provider we have to inject it into the WCF pipeline. This can be done in code or in the web.config file. Personally I prefer the web.config, but that’s a matter of taste.

To add behaviors to a WCF service, you have to create a class that implements IServiceBehavior. WCF calls the method ApplyDispatchBehavior when its loading the service and before it will start accepting client requests. In this method we will inject our custom instance provider.

public class NinjectBehaviorAttribute : Attribute, IServiceBehavior
{
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        Type serviceType = serviceDescription.ServiceType;
        IInstanceProvider instanceProvider = new NinjectInstanceProvider(new StandardKernel(), serviceType);

        foreach(ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
            {
                DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
                dispatchRuntime.InstanceProvider = instanceProvider;
            }
        }
    }

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

If the service behavior class extends from .Net Attribute class; you can use it to annotate your service implementation. WCF is able to detect such service behaviors and it will load and attach them to the service.

[NinjectBehaviorAttribute]
public class HelloService : IHelloService
{
}

If you don’t want to add the service behavior in code, but instead in the web.config file, you have to implement a class that extends from BehaviorExtensionElement. Again, this is very easy to do:

public class NinjectBehaviorExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof (NinjectBehaviorAttribute); }
    }

    protected override object CreateBehavior()
    {
        return new NinjectBehaviorAttribute();
    }
}

Now we can configure WCF to use Ninject from the web.config:

<system.serviceModel>
  <services>
    <!-- A dummy WCF service ... -->
    <service name="WcfIoc.HelloService" behaviorConfiguration="HelloServiceBehavior">
      <endpoint address=""
                binding="wsHttpBinding"
                contract="WcfIoc.IHelloService" />
    </service>
  </services>

  <behaviors>
    <serviceBehaviors>
      <behavior name="HelloServiceBehavior">
        <!-- Add the Ninject behavior to the WCF service. -->
        <ninject />
      </behavior>
    </serviceBehaviors>
  </behaviors>

  <extensions>
    <behaviorExtensions>
      <!-- Add the Ninject behavior extension -->
      <add name="ninject"
            type="WcfIoc.NinjectBehaviorExtensionElement, WcfIoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>
</system.serviceModel>

We are done Glimlach I think that everybody will agree that WCF is very powerful and configurable, yet at the same time its internals are very intuitive and easy to understand.

Advertisements
Categories: C#, IoC, Ninject, WCF
  1. J
    July 12, 2011 at 21:34

    Thanks for this post.
    Where do you write your Ninject bindings ?
    in the NinjectBehaviorAttribute.ApplyDispatchBehavior method like this http://ideone.com/jk8xW ?

    • pieterderycke
      July 13, 2011 at 19:08

      Yes, in the ApplyDispatchBehavior of IServiceBehavior I inject my custom instance provider that relies on Ninject for creating instances. Is not everything in the article clear for you?

      • August 16, 2011 at 09:46

        Hi Pieter,

        Thanks very much for this post. I’ve been looking for a do-it-yourself solution because I hate using the Ninject Extensions without knowing what’s going on.

        As a slight improvement, would it not be a cleaner solution to create your bindings in a custom NinjectModule and pass an instance of that to the new StandardKernel() call in the ApplyDispatchBehaviour method? That way your bindings are separated from your ServiceBehaviour code.

        Best Regards,

        Erik

      • pieterderycke
        August 16, 2011 at 10:01

        Hello Erik,

        If you would use the attribute way to inject the IoC container in the pipeline, it would be simple to do. Passing a NinjectModule to a behavior defined in the config file is also possible, but would require some extra code.

        Ofcourse this was just an example, you can always extend it 🙂

        Kind regards,
        Pieter

  2. Iroel Perez
    November 10, 2012 at 04:56

    Thank you very much for the post. This was a piece I was looking to complete the puzzle of combining WCF and Iocs.

  3. August 9, 2013 at 14:03

    I think you’ll want to add a call to your ReleaseInstance method like so:

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
    kernel.Release(instance);
    }

    otherwise you’ll run into resource issues

  1. July 30, 2016 at 18:15

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: