Sunday, April 17, 2016

WCF - Dependency Injection using Ninject

In this example we are going to create a simple WCF Service using Dependency Injection with Ninject.


Step #1 - Create a WCF Service Application project



Step #2 - Create an interface for your business class

This is shown in the following code.

namespace WCF.DependencyInjection
{
    public interface IDependencyInjectionApp
    {
        string GetData(int value);
    }

}

Step #3 - Implement the interface

Create a class that implements the interface created on the Step #2. This is shown in the following code.

namespace WCF.DependencyInjection

{
    public class DependencyInjectionApp : IDependencyInjectionApp
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
    }

}


Step #4 - Install the Ninject package

Step #5 - Register the dependencies

Create a class to register the dependencies using the Ninject. This is shown in the following code.

using Ninject;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WCF.DependencyInjection

{
    public static class NinjectContainer
    {
        private static IKernel _kernel;
        static NinjectContainer()
        {
            _kernel = new StandardKernel();
            ConfigureContainer();

        }

        static void ConfigureContainer()
        {
            _kernel.Bind<IDependencyInjectionApp>().To<DependencyInjectionApp>();
        }
        public static object Resolve(Type service)
        {
            return _kernel.Get(service);
        }
    }

}


Step #6 - Create the instance provider

Now that the dependencies are registered we can create a custom instance provider.To create a custom instance provider, create a class that implements IInstanceProvider. This is shown in the following code.

using System;

using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Web;

namespace WCF.DependencyInjection

{
    public class DependencyInjectionInstanceProvider : IInstanceProvider
    {
        private readonly Type _serviceType;

        /// <summary>

        /// Initializes a new instance of the <see cref="DependencyInjectionInstanceProvider"/> class.
        /// </summary>
        /// <param name="serviceType">Type of the service.</param>
        public DependencyInjectionInstanceProvider(Type serviceType)
        {
            _serviceType = serviceType;
        }

        /// <summary>

        /// Returns a service object given the specified <see cref="T:System.ServiceModel.InstanceContext"/> object.
        /// </summary>
        /// <param name="instanceContext">The current <see cref="T:System.ServiceModel.InstanceContext"/> object.</param>
        /// <returns>A user-defined service object.</returns>
        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }

        /// <summary>

        /// Returns a service object given the specified <see cref="T:System.ServiceModel.InstanceContext"/> object.
        /// </summary>
        /// <param name="instanceContext">The current <see cref="T:System.ServiceModel.InstanceContext"/> object.</param>
        /// <param name="message">The message that triggered the creation of a service object.</param>
        /// <returns>The service object.</returns>
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return NinjectContainer.Resolve(_serviceType);
        }

        /// <summary>

        /// Called when an <see cref="T:System.ServiceModel.InstanceContext"/> object recycles a service object.
        /// </summary>
        /// <param name="instanceContext">The service's instance context.</param>
        /// <param name="instance">The service object to be recycled.</param>
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }



}


Step #7 - Create the service behavior.

The next step is to create a service behavior that registers the instance provider. This is shown in the following code.

using System;

using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using WCF.DependencyInjection;
/// <summary>
/// A custom service behavior which will register the dependency injection instance provider.
/// </summary>
public class DependencyInjectionServiceBehavior : Attribute, IServiceBehavior
{
    #region IServiceBehavior Members

    /// <summary>

    /// Provides the ability to pass custom data to binding elements to support the contract implementation.
    /// </summary>
    /// <param name="serviceDescription">The service description of the service.</param>
    /// <param name="serviceHostBase">The host of the service.</param>
    /// <param name="endpoints">The service endpoints.</param>
    /// <param name="bindingParameters">Custom objects to which binding elements have access.</param>
    public void AddBindingParameters(ServiceDescription serviceDescription,
        System.ServiceModel.ServiceHostBase serviceHostBase,
        System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
        System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    { }

    /// <summary>

    /// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, message or parameter interceptors, security extensions, and other custom extension objects.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param>
    /// <param name="serviceHostBase">The host that is currently being built.</param>
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
        foreach (var cdb in serviceHostBase.ChannelDispatchers)
        {
            var cd = cdb as ChannelDispatcher;

            if (cd != null)

            {
                foreach (var ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = new DependencyInjectionInstanceProvider(serviceDescription.ServiceType);
                }
            }
        }
    }

    /// <summary>

    /// Provides the ability to inspect the service host and the service description to confirm that the service can run successfully.
    /// </summary>
    /// <param name="serviceDescription">The service description.</param>
    /// <param name="serviceHostBase">The service host that is currently being constructed.</param>
    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    { }

    #endregion

}

Step #8 - Add the behavior to the service

Now that we have the instances registered and the behavior created we just need  add the behavior to your service and set the parameters in the service constructor. This is shown in the following code.



namespace WCF.DependencyInjection

{

    [DependencyInjectionServiceBehavior]

    public class DependencyInjectionService : IDependencyInjectionService

    {

        private readonly IDependencyInjectionApp _iApp;
        public DependencyInjectionService(IDependencyInjectionApp iApp)
        {
            _iApp = iApp;
        }
        public string GetData(int value)
        {
            return _iApp.GetData(value);
        }
    }
}

The behavior will resolve all the instances that the service needs and pass these instances to the contructor as parameters, but remember, you need to register the instances as we did in the Step #5.

The full example can be downloaded here. Enjoy!

4 comments:

  1. Really nice blog post.provided a helpful information.I hope that you will post more updates like this
    Dot NET Online Training

    ReplyDelete
  2. We are really grateful for your blog post. You will find a lot of approaches after visiting your post. I was exactly searching for. Thanks for such post and please keep it up. Great work. two shot injection moulding

    ReplyDelete
  3. I’m going to read this. I’ll be sure to come back. thanks for sharing. and also This article gives the light in which we can observe the reality. this is very nice one and gives indepth information. thanks for this nice article... 2k moulding

    ReplyDelete
  4. Is it possible to get a merit casino? - Deccasino.com
    A review of 메리트카지노 the casino's games and features. 샌즈카지노 All 메리트 카지노 주소 games available online are by software providers. How do you use them? Is

    ReplyDelete

Microservices – Creating Resilient Services

Dealing with unexpected failures is one of the hardest problems to solve, especially in a distributed system . A microservice needs to...