WCF + Unity App. Block


The Inversion of Control  (IoC) and Dependency Injection (DI) Pattern are very common nowadays and it represent an excellent approach to assemble projects into a cohesive application. Martin Fowler describes those patterns in this article

Enterprise Library gives us an IoC Container within Unity App. Block. This App. Block makes our lives easier when we’re about to use the IoC and DI patterns and some Creational Patterns as well.

But how do integrate WCF with Unity App. Block? The main issue is that WCF is responsible for instantiate the concrete service classes. So what we have to do is to modify this behavior, using some extensibility points of WCF and delegate to Unity App. Block the responsibility of instantiate the concrete service classes. Doing that, we’re able to enjoy all the benefits of the IoC Container and DI, even using WCF.

Remember that in this post I’m using Unity App. Block as our IoC Container but the strategy applies to any IoC container you like.

So, let’s go to hands on experience:

Creating Your Instance Provider based on Unity App. Block

WCF gives us the possibility of extend the way we create concrete service classes instances. In order to do that we should inherit from System.ServiceModel.Dispatcher.IInstanceProvider and override the GetInstance method. In this method we should use the Unity App. Block Container to manage the instances creation as follow:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity;

namespace Sample.WCF.Extensions.Unity
{
    /// <summary>
    /// Creates the service instance using Unity App.block
    /// </summary>
    public class UnityInstanceProvider : System.ServiceModel.Dispatcher.IInstanceProvider
    {
        /// <summary>
        /// Unity Container
        /// </summary>
        public IUnityContainer UnityContainer { get; set; }

        /// <summary>
        /// Service Type to Instantiate
        /// </summary>
        public Type ServiceType { get; set; }

        public UnityInstanceProvider() :this(null){}

        public UnityInstanceProvider(Type serviceType)
        {
            this.ServiceType = serviceType;
            this.UnityContainer = new UnityContainer();
        }

        #region IInstanceProvider Members

        public object GetInstance(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
        {
            //Check if the container is available
            if (this.UnityContainer != null)
            {
                /*
                 * Creates the service instance using Unity App. Block (DI and IoC)
                 * */
                return this.UnityContainer.Resolve(this.ServiceType);
            }

            return instanceContext;
        }

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

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

        #endregion
    }
}

Creating a Service Behavior

In order to use the Custom Instance Provider that we’ve created we should build a Custom Service Behavior and override the ApplyDispatchBehavior method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity;
using System.ServiceModel.Dispatcher;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;

namespace Sample.WCF.Extensions.Unity
{
    public class UnityServiceBehavior : System.ServiceModel.Description.IServiceBehavior
    {
        /// <summary>
        /// The Instance Provider Reference
        /// </summary>
        private UnityInstanceProvider InstanceProvider { get; set; }

        private void ConfigureUnityContainer(IUnityContainer unityContainer)
        {
            //Loads the Unity Section Handler and its configuration
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

            //Configures the container
            section.Containers.Default.Configure(unityContainer);
        }

        public UnityServiceBehavior()
        {
            //Creates the UnityInstanceProvider
            this.InstanceProvider = new UnityInstanceProvider();

            this.InstanceProvider.UnityContainer = new UnityContainer();

            this.ConfigureUnityContainer(this.InstanceProvider.UnityContainer);

        }

        #region IServiceBehavior Members

        public void AddBindingParameters(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<System.ServiceModel.Description.ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher cd = cdb as ChannelDispatcher;

                if (cd != null)
                {
                    foreach (EndpointDispatcher ed in cd.Endpoints)
                    {
                        //Indicates to instance provider the Service Type
                        this.InstanceProvider.ServiceType = serviceDescription.ServiceType;

                        //Sets the UnityInstanceProvider Foreach EndpointDispatcher
                        ed.DispatchRuntime.InstanceProvider = this.InstanceProvider;
                    }
                }
            }
        }

        public void Validate(System.ServiceModel.Description.ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }

        #endregion
    }
}

Configuring The Unity App. Block Section

The Unity App. Block works in two different ways. You can configure the IoC Container using a config file, our hard coding the IoC Container behavior. I often use the first approach (config file).

To configure the Unity App. Block we should declare a Section in the web.config file:

<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

After, we have to point this section to an external file (that really configures the IoC Container).


<unity configSource="YourConfigFile.config">

</unity>

To see how to configure the Unity App. Block Container check out this link: http://msdn.microsoft.com/en-us/library/ff647427.aspx

Two different approaches to configure a Custom Service Behavior

There are two different approaches to insert the custom service behavior that we’ve created.

1. BehaviorExtensionElement Approach

In this approach we should indicate foreach Service we have that we would like to integrate it with Unity App. Block. In order to do that we have to create BehaviorExtensionElement and configure it in the web.config file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity;

namespace Sample.WCF.Extensions.Unity
{
    public class UnityBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement
    {
        public UnityBehaviorExtensionElement()
        {
        }

        public override Type BehaviorType
        {
            //Returns the type of UnityServiceBehavior
            get { return typeof(UnityServiceBehavior); }
        }

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

Registering it in the web.config file:

  <extensions>
      <behaviorExtensions>
        <add name="UnityWCF" type="Sample.WCF.Extensions.Unity.UnityBehaviorExtensionElement, Sample.WCF.Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
	<behaviors>
			<serviceBehaviors>
				<behavior name="Sample.WCF.Extensions.SampleServiceBehavior">
                                        <UnityWCF />
					<serviceMetadata httpGetEnabled="true"/>
					<serviceDebug includeExceptionDetailInFaults="false"/>
				</behavior>
                          </serviceBehaviors>
        </behaviors>

2. Service Host Factory Approach

In this approach we use a custom Service Host Factory and inject the Custom Service Behavior and its Custom Instance Provider foreach service without needing to indicate that in the web.config file:

The first Step is to create a Custom Service Host Factory and a Custom Service Host:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;

namespace Sample.WCF.Extensions.Unity
{
    public class UnityServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory
    {
        protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            //Creates the unity service host
            UnityServiceHost unityServiceHost = new UnityServiceHost(serviceType, baseAddresses);

            return unityServiceHost;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;

namespace Sample.WCF.Extensions.Unity
{
    public class UnityServiceHost : System.ServiceModel.ServiceHost
    {
        public UnityServiceHost() : base()
        {
        }

        public UnityServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses)
        {
        }

        protected override void OnOpening()
        {
            //Verifies if the UnityServiceBehavior is already attached
            if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null)
            {
                //Attach the UnityServiceBehavior
                this.Description.Behaviors.Add(new UnityServiceBehavior());
            }

            base.OnOpening();
        }
    }
}

After that we need to chance the service Factory in your .svc file:


<%@ ServiceHost Debug="true" Service="Sample.WCF.Extensions.SampleService" CodeBehind="SampleService.svc.cs" Factory="Sample.WCF.Extensions.Unity.UnityServiceHostFactory, Sample.WCF.Extensions" %>

Remember that in this post I’m using Unity App. Block as our IoC Container but the strategy applies to any IoC container you like, ok?

[]´s

About these ads

About Rafael Tolotti

Brazilian software architect, post graduated in Strategic Management of Information Technology. Microsoft Commerce Server specialist interested in software architectures and design patterns. He's also interested in team management, risk management, project management and agile software development. As a sports lover is passionate about soccer and tennis as well.
This entry was posted in .NET Framework, Computer Science and tagged , , , , , , , . Bookmark the permalink.

2 Responses to WCF + Unity App. Block

  1. Arunkumar says:

    Hi Find the below code needs to be insted in the web.config file

    then Create a Unity.Config and insert the below similar code based on the solution structure.

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