Inversion of Control with WCF and Unity

Lately, I often talks with friends and colleagues about Inversion of Control (IOC) and WCF. Then, I’ve decided to publish this post and explain the necessary steps to get IoC in WCF. For this example, let’s get to use Unity ad framework for IoC.

First, the necessary components are:

  • InstanceProvider: it is the component that creates the service instance. It uses the UnityContainer;
  • ServiceBehavior: creates the InstanceProvider and allows to use it in the current context;
  • ServiceHost: handles the environment of our service. The ServiceHost configures the service for use and then it allows to apply the created ServiceBehavior instance;

We then get: UnityInstanceProvider, UnityServiceBehavior and UnityServiceHost.

UnityInstanceProvider

The first step is to create the InstanceProvider. The code is really simple:

  1: internal class UnityInstanceProvider : IInstanceProvider
  2: {
  3:     private readonly IUnityContainer container;
  4:     private readonly Type contractType;
  5: 
  6:     public UnityInstanceProvider(IUnityContainer container, Type contractType)
  7:     {
  8:         this.container = container;
  9:         this.contractType = contractType;
 10:     }
 11: 
 12:     public object GetInstance(InstanceContext instanceContext)
 13:     {
 14:         return GetInstance(instanceContext, null);
 15:     }
 16: 
 17:     public object GetInstance(InstanceContext instanceContext, Message message)
 18:     {
 19:         return container.Resolve(contractType);
 20:     }
 21: 
 22:     public void ReleaseInstance(InstanceContext instanceContext, object instance)
 23:     {
 24:         container.Teardown(instance);
 25:     }
 26: }

The first constructor’s parameters is the instance of the UnityContainer and the second is the specific endpoint contract. Both are used by the GetInstance to resolve the service’s instance. Naturally, the method could be better.

UnityServiceBehavior

The ServiceBehavior, as mentioned above, creates the InstanceProvider for the specifiv service endpoint:

  1: public class UnityServiceBehavior : IServiceBehavior
  2: {
  3:     private readonly IUnityContainer container;
  4: 
  5:     public UnityServiceBehavior(IUnityContainer container)
  6:     {
  7:         this.container = container;
  8:     }
  9: 
 10:     public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
 11:     {
 12:     }
 13: 
 14:     public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
 15:     {
 16:     }
 17: 
 18:     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
 19:     {
 20:         foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
 21:         {
 22:             foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
 23:             {
 24:                 if (endpointDispatcher.ContractName != "IMetadataExchange")
 25:                 {
 26:                     string contractName = endpointDispatcher.ContractName;
 27:                     ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
 28:                     endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(this.container, serviceEndpoint.Contract.ContractType);
 29:                 }
 30:             }
 31:         }
 32:     }
 33: }

The constructor gets from ServiceHost the container’s instance. Then the ApplyDispatchBehavior assigns the instance to the UnityInstanceProvider with the contracts used to resolve the service instance. Finally the UnityInstanceProvider is assigned to InstanceProvider property of DispatchRuntime for each EndpointDispatcher.

UnityServiceHost

The finaly step is to create the ServiceHost:

  1: public class UnityServiceHost : ServiceHost
  2: {
  3:     private IUnityContainer unityContainer;
  4: 
  5:     public UnityServiceHost(IUnityContainer unityContainer, Type serviceType) : base(serviceType)
  6:     {
  7:         this.unityContainer = unityContainer;
  8:     }
  9: 
 10:     protected override void OnOpening()
 11:     {
 12:         base.OnOpening();
 13: 
 14:         if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null)
 15:         {
 16:             this.Description.Behaviors.Add(new UnityServiceBehavior(this.unityContainer));
 17:         }
 18:     }
 19: }

The code is really simple. The ServiceHost's constructor gets the container and the service type as parameters. In the OnOpening method override the ServiceHost checks if the UnityServiceBehavior is already added to Service’s behaviors. If not, it creates the instance and pass the container’s instance to the contructor.

Utilizzo in una applicazione console self-hosted

Now we are ready. This is the sample configuration we'll use in our service:

  1: <?xml version="1.0" encoding="utf-8" ?>
  2: <configuration>
  3:   <configSections>
  4:     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  5:   </configSections>
  6:   
  7:   <unity>
  8: 
  9:     <containers>
 10: 
 11:       <container>
 12:         <types>
 13:           
 14:           <type type="DotNetSide.WCF.IoC.Console.InnerBookService, DotNetSide.WCF.IoC.Console"
 15:                 name="inner"/>
 16: 
 17:           <type type="DotNetSide.WCF.IoC.Console.IBookService, DotNetSide.WCF.IoC.Console"
 18:                 mapTo="DotNetSide.WCF.IoC.Console.BookService, DotNetSide.WCF.IoC.Console">
 19:             <typeConfig>
 20:               <constructor>
 21:                 <param name="innerService" parameterType="DotNetSide.WCF.IoC.Console.InnerBookService, DotNetSide.WCF.IoC.Console">
 22:                   <dependency name="inner" />
 23:                 </param>
 24:               </constructor>
 25:             </typeConfig>
 26:           </type>
 27: 
 28:         </types>
 29:       </container>
 30: 
 31:     </containers>
 32:     
 33:   </unity>
 34: 
 35: </configuration>

Simply must be created an InnerBookService instance and then get it into the BookService’s constructor, an IBookService contract implementation:

  1: [ServiceContract]
  2: internal interface IBookService
  3: {
  4:     [OperationContract]
  5:     Book ReadBook(string bookId);
  6: }
  7: 
  8: class BookService : IBookService
  9: {
 10:     private readonly InnerBookService innerService;
 11: 
 12:     public BookService(InnerBookService innerService)
 13:     {
 14:         this.innerService = innerService;
 15:     }
 16: 
 17:     public Book ReadBook(string bookId)
 18:     {
 19:         return this.innerService.ReadBook(bookId);
 20:     }
 21: }
 22: 
 23: class InnerBookService
 24: {
 25:     public Book ReadBook(string bookId)
 26:     {
 27:         return new Book()
 28:         {
 29:             Title = "WCF",
 30:             Description = "A book on Windows Communication Foundation"
 31:         };
 32:     }
 33: }

Finally we build the ServiceHost with the instance of the UnityContainer:

  1: var unityContainer = new UnityContainer();
  2: var configurationSection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
  3: configurationSection.Containers.Default.Configure(unityContainer);
  4: 
  5: Uri serviceAddress = new Uri("http://localhost:9001/BookService");
  6: Uri mexAddress = new Uri("http://localhost:9001/BookService/mex");
  7: using (UnityServiceHost host = new UnityServiceHost(unityContainer, unityContainer.Resolve<IBookService>().GetType()))
  8: {
  9:     host.Description.Behaviors.Add(new ServiceMetadataBehavior());
 10:     host.AddServiceEndpoint(typeof(IBookService), new BasicHttpBinding(), serviceAddress);
 11:     host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), mexAddress);
 12: 
 13:     host.Open();
 14: 
 15:     System.Console.Read();
 16: 
 17:     host.Close();
 18: }

We also add a WS-MetadataExchange endpoint. In this way we can create our client and try to call the service.

Actually, the UnityServiceHost is not necessary but helps us to encapsulate the behavior creation. We can also write:

  1: using (ServiceHost host = new ServiceHost(unityContainer.Resolve<IBookService>().GetType()))
  2: {
  3:     host.Description.Behaviors.Add(new UnityServiceBehavior(unityContainer));
  4:     // ...
  5: }
  6: 

Feedback?

bye

kick it on DotNetKicks.com

24 Comments

  • Hello,

    Do you know if Unity will be replaced with MEF?

  • Is is possible to get the complete solution for download, as I am working on wcf and IoC

  • Great post, can you please provide a download link for the sample code? Thanks again!

  • I would like to register a chain of methods to be called before and after a target imploementation. This post comes close to interception but would you mind providing a little more feedback on implementing multiple interception methods?

  • What's up everyone, it's my first go to see at this site,
    and paragraph is really fruitful in favor of me, keep up posting these types of posts.

  • You can eliminate 3 to unique pounds in one particular week.
    In which to lose weight, chew on lean meat,
    combined with prepare it all through a healthy process.
    It can get a number of weeks before ones doctor can appear the right anti-depressant to fit an condition.

  • We stumbled over here from a different web address and
    thought I might as well check things out. I like
    what I see so i am just following you. Look forward to looking over your web page repeatedly.

  • Hi there just wanted to give you a brief heads up and let you know a few
    of the pictures aren't loading correctly. I'm not sure why but I think its a
    linking issue. I've tried it in two different internet browsers and both show the same results.

  • Thanks for another great article. Where else may anyone get that type of info in such an ideal way of writing?
    I have a presentation subsequent week, and I am
    at the search for such info.

  • Wow, wonderful blog layout! How long have you been blogging for?
    you make blogging look easy. The overall look of your
    website is fantastic, as well as the content!

  • Good day, your websites are really good. We do appreciate you excellent posts.

  • Your current report has proven useful to us. It’s very informative
    and you're simply naturally very knowledgeable in this field. You have exposed my face for you to different thoughts about this specific subject together with intriguing, notable and reliable articles.

  • Nice post. I used to be checking constantly this blog and I am inspired!
    Extremely useful info specially the closing part :) I deal
    with such info much. I was looking for this certain
    information for a long time. Thanks and best of luck.

  • Your current report features confirmed helpful to myself.
    It’s very helpful and you really are certainly quite experienced of this type.

    You get opened my personal eyes in order to varying opinion of this
    kind of subject with intriguing and reliable content material.

  • I'm now not sure the place you are getting your information, but good topic. I must spend some time learning much more or understanding more. Thanks for wonderful info I used to be looking for this info for my mission.

  • Your own write-up provides established useful to me. It’s quite educational and you're obviously extremely educated in this region. You get opened my personal sight in order to numerous opinion of this subject matter using interesting and sound content material.

  • Great delivery. Great arguments. Keep up the great spirit.

  • Hello friends, how is the whole thing, and what you desire to say
    about this paragraph, in my view its truly remarkable designed
    for me.

  • Generally I don't read article on blogs, however I wish to say that this write-up very forced me to check out and do it! Your writing style has been amazed me. Thanks, quite nice post.

  • I know this website provides quality based content and additional material, is there any other site which
    presents these kinds of things in quality?

  • My partner and I stumbled over here different web
    address and thought I might as well check things out.
    I like what I see so now i am following you. Look forward to looking at your web page
    yet again.

  • Hi I am so glad I found your website, I really found
    you by error, while I was searching on Aol for something else,
    Regardless I am here now and would just like to say kudos for a tremendous post and a all round
    entertaining blog (I also love the theme/design), I don’t have time to look over it all at the minute but
    I have saved it and also added in your RSS feeds, so when I have time I will be back to read much
    more, Please do keep up the excellent work.

  • Your own report has verified helpful to me. It’s very educational and
    you really are obviously very experienced in this region.
    You get opened up my personal sight in order to different
    opinion of this subject matter with interesting and reliable written content.

  • Hi there to every one, the contents present at this site are truly awesome for people knowledge, well, keep up
    the nice work fellows.

Comments have been disabled for this content.