Click here to Skip to main content
Click here to Skip to main content

DI/IOCs

, 2 Jan 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
A look at Dependency Injection and IOC containers.

Introduction

At the place where I work, we have started developing a new project using all sorts of Agile/SCRUM/Xp methodologies, and we were actually lucky enough to have Martin Fowler's company: ThoughtWorks, come in and teach us a few things. One of these things was Dependency Injection. Now, there are already a number of articles here at CodeProject about DI, but after reading a few of them, I felt there was still room for another one, as I wanted to talk a little bit about what it is trying to solve, which is something that some of the other articles didn't seem to cover.

What IOCs Solve

Typically, when we write software, we are writing software that calls on service classes, not necessarily Web Services; what I mean are classes that provide some function when called. Consider the following code, where I am expecting to be able to use some sort of logging service and some sort of exception reporting service:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class SomeClass
    {
        private ILoggingStrategy logger = null;
        private IExceptionReporter exreporter = null;

        public SomeClass()
        {
              //create a SQL logger
            logger = new SQLLogger();
        }


        public void SomeMethod()
        {
            //create a SQL Exception reporter
            exreporter = new SQLExceptionReporter();
        }
    }
}

More often that not, if an object needs to gain access to a certain service, the actual object takes on the role of creating an instance of the service (as seen above) that the code needs. This can take many forms: it could be done in a constructor, or by holding a direct reference to a service object, or could even use some sort of service locator to provide an instance of a particular service object. What all these approaches are doing is holding references of service objects within the consuming object, which strongly ties the consuming object to the instance of the service objects, which may not be desirable, as the consumer now depends on the service objects.

What Dependency Injection does, is allow this dependency on service classes to be inverted, so they are no longer created in the consuming object.

DI can either use property or constructor parameters, which must be of the desired service types, and when the object that needs these service types is created, an implementation of the desired service type is automatically passed to the object being constructed by some external mechanism. Bingo, no more internal dependencies on service types within the consuming object.

Dependency Injection is more flexible than holding internal references, as it allows an alternative implementation of a given service to be created and literally injected into the object that requires the service type. The actual service implementation type may be configured in a config file, so one could easily swap out one service type implementation for another. Imagine a situation where you have written some software that needs to work with SQL Server and then your company decides you must also support Oracle; if we use DI and config files, we could configure the solution to hold either a Oracle service type or a SQL Server service type, and the code that utilises these services could work without being recompiled.

Another area where DI is especially useful is when using Mocks; you can use a Mock service type by simply setting the config file to point at a Mock implementation of some service. This is very useful. We have actually done just this at work, and it allows us a lot of flexibility with our Unit/Integration tests.

Obviously, with this level of configurability comes what is known as explosion of interfaces, so DI also has its own drawbacks. However, the benefits that DI can bring could easily outweigh the number of interfaces that you will wind up working with. Obviously, there should be a valid and just reason to use DI; it's worth having a think about though.

There are a few good DI implementations out there which allow the configuration of types to be done via config files/special attributes. Generally, these frameworks all offer DI under the umbrella name of IOC, which stands for "Inversion of control".

According to Wikipedia, IOC is:

"Inversion of Control, or IoC, is an abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to the traditional architecture of software libraries."

Pretty much most (if not all) of the IOC frameworks out there simply act as containers for service types. You can think of the container as a special/clever dictionary that knows how to grab a service type and provide it when needed. The basic idea is that you have a container that knows about all the service types (or other types you wish to use with DI). The IOC framework will inject these service types when an object that requires one of these known/stored (in the container) service types need one.

In the remainder of this article, I will talk about how to do DI using some of the free frameworks out there, and at the end of the article, I will provide links to more DI/IOC frameworks that you may choose to investigate by yourself.

The Common Demo Code Example

The attached demo code contains three projects:

  • CastleWindsorIOC: Shows how to work with constructor DI and Generics support
  • UnityIOC: Shows how to work with constructor DI and Generics support
  • UnityIOCPropertyResolution: Shows how to work with property DI

Both the CastleWindsorIOC and the UnityIOC projects set out to demonstrate exactly the same problem. The problem that they are setting out to demonstrate are quite simple. There is a single interface called IMessageFormatter which has two implementations: DateTimeMessageFormatter and SimpleMessageFormatter, which can be used by providing the correct settings in the config file.

There is also an example of how to work with a IGenericFormatter<T> generic interface, where the implementation is done in a class called DummyObjectFormatter.

There is also a simple Form (Form1) object that requires a IMessageFormatter and a IGenericFormatter<DummyObject> implementation passed into the constructor in order to work correctly.

This may become clearer if I show you a class diagram.

Castle Windsor Container

The Castle Windsor container is part of the Castle project, and can be downloaded at http://www.castleproject.org/.

The basic idea behind using the Castle Windsor container is that you have a container that can be configured though code/config files.

Castle Windsor Container: Config

I like to work with a config file as it offers the greatest level of flexibility, as we can literally alter the config file without the need to recompile the code.

Here is an example config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <!-- Custom Config Sections -->
  <configSections>
    <section
        name="castle"
        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
  </configSections>


  <!-- Castle Config Section -->
  <castle>
    <components>

      <!-- Alternative Message Provider 
          
      <component
        id="CurrentFormatter"
        service="CastleWindsorIOC.IMessageFormatter, CastleWindsorIOC"
        type="CastleWindsorIOC.SimpleMessageFormatter, CastleWindsorIOC" />
          
      -->

      <component
        id="CurrentFormatter"
        service="CastleWindsorIOC.IMessageFormatter, CastleWindsorIOC"
        type="CastleWindsorIOC.DateTimeMessageFormatter, CastleWindsorIOC" />

      <component id="DummyObjectFormatter"
        service="CastleWindsorIOC.IGenericFormatter`1[[CastleWindsorIOC.DummyObject, 
                 CastleWindsorIOC]], CastleWindsorIOC"
        type="CastleWindsorIOC.DummyObjectFormatter, CastleWindsorIOC"/>

    </components>
  </castle>

</configuration>

It can be seen that we simply create a custom Castle config section, and in that custom Castle section, we configure the container to tell it what types it should be able to resolve. This is done via a new component element per type that is required.

We can see that this config files has two types (one if commented out, which you could uncomment to try it out, but don't forget to comment the current one if you want to try the currently commented one) which are two different implementations of the same IMessageFormatter interface, thus effectively providing two different services, albeit very simple services, in this case.

Castle Windsor Container: Constructor Support

As you saw from the class diagram above, there is a IMessageFormatter interface that has two different implementations (SimpleMessageFormatter and DateTimeMessageFormatter). The config file that you just saw shows how to add these types to the Castle Windsor container.

So how do we go about using one of these types from the Castle Windsor container? Well, that's fairly simple. We just do something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;
using Castle.Core.Resource;

namespace CastleWindsorIOC
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            IWindsorContainer container =
                new WindsorContainer(
                    new XmlInterpreter(new ConfigResource("castle")));

            // use the Current Message Formatter (see the App.Config)
            var currentIMessageFormatter =
                (IMessageFormatter)container.Resolve("CurrentFormatter");

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1(currentIMessageFormatter));
        }
    }
}

It can be seen from this example that we are firstly configuring the Castle Windsor container and then we are obtaining all the types we need from the container, and then constructing a new Form1 object and passing these container objects to the constructor of the Form1 object.

Let's have a look at the Form1 code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace CastleWindsorIOC
{
    public partial class Form1 : Form
    {
        private IMessageFormatter msgFormatter;
        private int currentMessageCount = 0;

        public Form1()
        {
            InitializeComponent();
        }

        public Form1(IMessageFormatter msgFormatter)
            : this()
        {
            this.msgFormatter = msgFormatter;
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            lstItems.Items.Add(msgFormatter.FormatMessage(
                String.Format("CurrentMessage {0}",
                currentMessageCount++)));
        }

        .....
        .....
    }
}

From here, we can see that the types that the Form1 object needs for its constructor have been resolved by the Castle Windsor container and supplied to the Form1 constructor. Cool.

So what happens when we run the app? We get a message formatted using the current (App.Config type that is used) IMessageFormatter interface implementation.

Castle Windsor Container: Generics Support

So that's cool, we now have DI working with constructor parameters using the Castle Windsor container. So what else can we do? Surely there is more. Well yeah, there is actually. We can use the DI with Generics. Here is an example of how to do this.

The demo code has an IGenericFormatter<T> interface which is declared like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CastleWindsorIOC
{
    public interface IGenericFormatter<T>
    {
        String FormatMessage(T valueIn);
    }
}

Where the demo code also contains an implementation of this interface as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CastleWindsorIOC
{
    public class DummyObjectFormatter : IGenericFormatter<DummyObject>
    {

        public string FormatMessage(DummyObject valueIn)
        {
            return String.Format("The value was {0}", valueIn.ToString());
        }

    }
}

Here is what you need to do for the App.Config file to support Generics:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <!-- Custom Config Sections -->
  <configSections>
    <section
      name="castle"
      type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
  </configSections>

  <!-- Castle Config Section -->
  <castle>
    <components>

      <!-- Alternative Message Provider 
          
      <component
        id="CurrentFormatter"
        service="CastleWindsorIOC.IMessageFormatter, CastleWindsorIOC"
        type="CastleWindsorIOC.SimpleMessageFormatter, CastleWindsorIOC" />
          
      -->

      <component
        id="CurrentFormatter"
        service="CastleWindsorIOC.IMessageFormatter, CastleWindsorIOC"
        type="CastleWindsorIOC.DateTimeMessageFormatter, CastleWindsorIOC" />

      <component id="DummyObjectFormatter"
         service="CastleWindsorIOC.IGenericFormatter`1[[CastleWindsorIOC.DummyObject, 
                  CastleWindsorIOC]], CastleWindsorIOC"
         type="CastleWindsorIOC.DummyObjectFormatter, CastleWindsorIOC"/>

    </components>
  </castle>

</configuration>

In this case, I am using a type of Unity.DummyObject to be the type that is used for the IGenericFormatter<T> implementation, which if you remember was defined like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CastleWindsorIOC
{
    public class DummyObjectFormatter : 
        IGenericFormatter<DummyObject>
    {
        public string FormatMessage(DummyObject valueIn)
        {
            return String.Format("The value was {0}", 
                valueIn.ToString());
        }
    }
}

We can see that DummyObjectFormatter is expecting to be passed a DummyObject from the Castle Windsor container. The config file section I just showed you does just that.

How do we resolve this using the Castle Windsor container? Well, we simply do the following:

// use the generic Message Formatter
var dummyObjectFormatter =
    (IGenericFormatter<dummyobject>)container.Resolve("DummyObjectFormatter");

And if we examine the constructor of a Form1 object that requires such a type to be provided, it should be pretty obvious that all we need to do is pass the container obtained generic object to the Form1 object's constructor.

public Form1(IMessageFormatter msgFormatter,
    IGenericFormatter<dummyobject> actualGenTest)
    : this()
{
    this.msgFormatter = msgFormatter;
    this.actualGenTest = actualGenTest;
}

Castle Windsor Container: Property Support

Is should be possible to not only inject constructor parameters but also use DI/IOC to inject property values. I had a go of this using the Castle Windsor container, but didn't get any where with it. I am sure it can be done, I just didn't manage it... But like I say, I think it is possible.

Unity Container

Unity is a Microsoft application block offering, from the Patterns & Practices group, and can be downloaded at http://msdn.microsoft.com/en-us/library/dd203101.aspx.

The basic idea behind using Unity is that you have a container that can be configured though code/config files, much the same as Castle Windsor. I think the best way to demonstrate this is by working through the same small example as we did with Castle Windsor above.

So let's do that.

Unity Container: Config

I like to work with a config file as it offers the greatest level of flexibility as we can literally alter the config file without the need to recompile the code.

Here is an example config file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <!-- Custom Config Sections -->
  <configSections>
    <section name="unity"
        type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
              Microsoft.Practices.Unity.Configuration" />
  </configSections>

  <!-- Unity Config Section -->
  <unity>
    <containers>
      <container>
        <types>

            <!-- Alternative Message Provider 

          &lt;type name="CurrentFormatter" 
              type="Unity.IMessageFormatter,Unity"
              mapTo="Unity.SimpleMessageFormatter,Unity"/&gt;
            -->
          
          <type name="CurrentFormatter"
              type="Unity.IMessageFormatter,Unity"
              mapTo="Unity.DateTimeMessageFormatter,Unity"/>


        </types>
      </container>
    </containers>
  </unity>

</configuration>

It can be seen that we simply create a custom Unity config section (much the same as Castle Windsor), and in that custom Unity section, we configure the container to tell the container which types it will know about at runtime.

We can see that this config file has two types (one if commented out, which you could uncomment to try it out, but don't forget to comment the current one if you want to try the currently commented one) which are two different implementations of the same IMessageFormatter interface, thus effectively providing two different services, albeit very simple services, in this case. It should still demonstrate the idea.

Unity Container: Constructor Support

We are using the same example as the Castle Windsor, where we use the same IMessageFormatter interface and have two different implementations of this interface (SimpleMessageFormatter and DateTimeMessageFormatter) that we saw in the Castle Windsor example above. The config file that you just saw shows how to add these types to the Unity container.

So how do we go about using one of these types from the Unity container? Well, that's fairly simple. We just do something like this:

namespace Unity
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            UnityContainer container = new UnityContainer();

            UnityConfigurationSection section = (UnityConfigurationSection)
                           ConfigurationManager.GetSection("unity");
            section.Containers.Default.Configure(container);

            // use the Current Message Formatter (see the App.Config)
            var currentIMessageFormatter =
                (IMessageFormatter)container.Resolve(
                    typeof(IMessageFormatter), "CurrentFormatter");

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1(currentIMessageFormatter));
        }
    }
}

It can be seen from this example that we are firstly configuring the Unity container, and then we are obtaining all the types we need from the container and then constructing a new Form1 object and passing these container objects to the constructor of the Form1 object.

Let's have a look at the Form1 code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.Unity;

namespace Unity
{
    public partial class Form1 : Form
    {
        private IMessageFormatter msgFormatter;
        private int currentMessageCount = 0;

        public Form1()
        {
            InitializeComponent();
        }

        public Form1(IMessageFormatter msgFormatter)
            : this()
        {
            this.msgFormatter = msgFormatter;
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            lstItems.Items.Add(msgFormatter.FormatMessage(
                String.Format("CurrentMessage {0}",
                currentMessageCount++)));
        }

        .....
        .....
    }
}

From here, we can see that the types that the Form1 object needs for its constructor have been resolved by the Unity container and supplied to the Form1 constructor. Cool.

So what happens when we run the app? Well, much the same as the Castle Windsor example; we get a message formatted using the current (App.Config type that is used) IMessageFormatter interface implementation.

Unity Container: Generics Support

So that's cool, we now have DI working with constructor parameters using the Unity container. What else can we do? Surely, there is more. Well yeah, there is actually. Much the same as Castle Windsor allowed us to work with Generics, so does Unity. Here is an example (again, using the same interfaces as the Castle Windsor example) of how to do this.

Here is what you need to do for the App.Config file to support Generics:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <!-- Custom Config Sections -->
  <configSections>
    <section name="unity"
        type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
              Microsoft.Practices.Unity.Configuration" />
  </configSections>

  <!-- Unity Config Section -->
  <unity>
    <containers>
      <container>
        <types>
          <type name="DummyObjectFormatter"
            type="Unity.IGenericFormatter`1[[Unity.DummyObject,Unity]], Unity"
            mapTo="Unity.DummyObjectFormatter,Unity"/>
        </types>
      </container>
    </containers>
  </unity>

</configuration>

In this case, I am using a type of Unity.DummyObject to be the type that is used for the IGenericFormatter<T> implementation which, if you remember, was defined like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Unity
{
    public class DummyObjectFormatter : 
        IGenericFormatter<DummyObject>
    {

        public string FormatMessage(DummyObject valueIn)
        {
            return String.Format("The value was {0}", 
                valueIn.ToString());
        }

    }
}

We can see that DummyObjectFormatter is expecting to be passed a DummyObject from the Unity container. The config file section I just showed you does just that.

How do we resolve this using the Unity container? Well, we simply do the following:

// use the IGenericFormatter Message Formatter
var dummyObjectFormatter =
    (IGenericFormatter<DummyObject>)
        container.Resolve(typeof(IGenericFormatter<DummyObject>),
        "DummyObjectFormatter");

And if we examine the constructor of a Form1 object that requires such a type to be provided, it should be pretty obvious that all we need to do is pass the container obtained generic object to the Form1 object's constructor.

public Form1(IMessageFormatter msgFormatter,
    IGenericFormatter<dummyobject> actualGenTest)
    : this()
{
    this.msgFormatter = msgFormatter;
    this.actualGenTest = actualGenTest;
}

Unity Container: Property Support

I was a little luckier when working with Unity than I was with Castle, and managed to get it to work by injecting property values as well as constructor values. I am positive Castle Windsor does this also, I think I just missed a trick somewhere.

Anyway, what you need to do in Unity to get a DI property to work is simply mark the property up with a special Unity attribute, which is shown below.

Here is a simple program file to launch a simple form which has a single property that requires a type to be supplied by the Unity container:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;

namespace UnityPropResolution
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            UnityContainer container = new UnityContainer();
            UnityConfigurationSection section = (UnityConfigurationSection)
                           ConfigurationManager.GetSection("unity");
            section.Containers.Default.Configure(container);

            Application.Run(container.Resolve<Form1>());
        }
    }
}

And here is the very simple form, take special note of the Unity [Dependency] attribute usage:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.Unity;

namespace UnityPropResolution
{
    public partial class Form1 : Form
    {

        private IMessageFormatter currentFormatter;
        private int currentMessageCount = 0;


        [Dependency("CurrentMessageFormatter")]
        public IMessageFormatter CurrentFormatter
        {
            get { return currentFormatter; }
            set { currentFormatter = value; }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void btnDoIt_Click(object sender, EventArgs e)
        {
            MessageBox.Show(CurrentFormatter.FormatMessage(
                String.Format("CurrentMessage {0}",
                currentMessageCount++)));
        }
    }
}

If we examine what this looks like when running, we can see the CurrentFormatter got resolved just fine, by the Unity container.

Quick Round Up

I quite like both Unity and Castle Windsor; I spent a bit of time examining other frameworks such as those listed below, but I leant towards the two I talked about here. In my humble opinion, both Unity and Castle Windsor are excellent products that fill the IOC/DI gap nicely, so if you find you would like to try these out, I would recommend either of these.

Other Frameworks Worth a Mention

  • Spring .NET: A quite mature (but I found quite tricky to use) framework covering all sorts of cool stuff, such as: AOP/Persistence/IOC/DI, amongst other things.
  • Pico .NET: A standalone IOC Container.
  • Lin Fu: This is a framework that offers DynamicProxy/IOC amongst other things; this is by a very, very talented guy called Philip Laureano, and he has published all the source code right here at CodeProject. He is very, very smart, and his ideas are well worth a look.

That's it

That is all I have to say. I hope this article has helped you a little. If you liked it, could you please be kind enough to leave a vote or a message? Thanks.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
 
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
 
Both of these at Sussex University UK.
 
Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
GeneralVisual Designer for XML files PinmemberDmitri Nesteruk2-Jan-09 4:35 
GeneralRe: Visual Designer for XML files PinmvpSacha Barber2-Jan-09 4:56 
GeneralRe: Visual Designer for XML files PinmemberDmitri Nesteruk2-Jan-09 4:59 
GeneralRe: Visual Designer for XML files PinmvpSacha Barber2-Jan-09 5:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 2 Jan 2009
Article Copyright 2009 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid