.NET Zone is brought to you in partnership with:

My name is Pieter De Rycke, I am a Belgian technical .Net architect working in the insurance sector. I am always eager to learn new technologies and I like to keep up with the latest innovations and trends in the IT sector. I am a big believer in web services for interoperability between platforms. Pieter is a DZone MVB and is not an employee of DZone and has posted 36 posts at DZone. You can read more from them at their website. View Full User Profile

Using an IoC container to create WCF service instances

05.09.2011
| 10188 views |
  • submit to reddit

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.

References
Published at DZone with permission of Pieter De Rycke, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)