![]() |
Languages »
C# »
General
Intermediate
License: The Code Project Open License (CPOL)
DI/IOCsBy Sacha BarberA look at Dependency Injection and IOC containers |
C# (C#2.0, C#3.0), .NET (.NET2.0, .NET3.0, .NET3.5), WPF, WinForms, Architect, Dev
|
||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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 Fowlers 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 is trying to solve, which is something that some of the other articles didn't seem to cover.
Typically when we write software we are writing software that calls on service classes, not nessecarily 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 a 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 consructed by some external mechanism. Bingo no more internal dependencies on service types within the consuming object.
Dependency Injection is more flexable that holding internal references, as it allows an alternative implemention of a given service to be created and literally injected into the object that requires the service type. The actual service implementaion 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 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 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 flexability with our Unit/Integration tests.
Obviously with this level of configurability, comes what is known as explosion of interfaces, so DI also has it's own drawn backs. However, the benefits that DI can bring could easily outway 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 attached demo code contains 3 projects:
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 2 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 an 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.

The Castle Windsor container is part of the Castle project, and can be downloaded at http://www.castleproject.org/
The basic idea behind using Castle Windsor container is that you have a container that can be configured though code/config files.
I like to work to 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 have 2 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 2 different implementations
of the same IMessageFormatter interface, thus effectively providing
2 different services, albeit very simple services in this case.
As you saw from the class diagram above there is a IMessageFormatter
interface that has 2 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.
Lets 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 use) IMessageFormatter interface implementation.
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 actually use 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 contain 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> implementaion,
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());
}
}
}
So we can see that the DummyObjectFormatter is expecting to be
passed a DummyObject from the Castle Windsor container. The config
file section I just showed you does just that.
So how do we resolve this using the Castle Windsor container, well we simply do the following:
// use the generic Message Formatter
var dummyObjectFormatter =
(IGenericFormatter)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 objects
constructor.
public Form1(IMessageFormatter msgFormatter,
IGenericFormatter actualGenTest)
: this()
{
this.msgFormatter = msgFormatter;
this.actualGenTest = actualGenTest;
}
Is should be possible to not only inject constructor parameters but also to 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 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.
I like to work to 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
<type name="CurrentFormatter"
type="Unity.IMessageFormatter,Unity"
mapTo="Unity.SimpleMessageFormatter,Unity"/>
-->
<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 files have 2 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 2 different implementations
of the same IMessageFormatter interface, thus effectively providing
2 different services, albeit very simple services in this case. It should still
demonstrate the idea.
We are using the same example as the Castle Windsor, where we use the same
IMessageFormatter interface and have 2 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.
Lets 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 use) IMessageFormatter interface implementation.
So that's cool, we now have DI working with constructor parameters using the Unity container. So 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 to does Unity allow us to work with generics. 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> implementaion,
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());
}
}
}
So we can see that the DummyObjectFormatter is expecting to be
passed a DummyObject from the Unity container. The config file
section I just showed you does just that.
So 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 objects
constructor.
public Form1(IMessageFormatter msgFormatter,
IGenericFormatter actualGenTest)
: this()
{
this.msgFormatter = msgFormatter;
this.actualGenTest = actualGenTest;
}
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.

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 2 I talked about here. In my humble opinion both Unit and Castle Windosr 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.
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
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 2 Jan 2009 Editor: |
Copyright 2009 by Sacha Barber Everything else Copyright © CodeProject, 1999-2010 Web22 | Advertise on the Code Project |