Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Dependency Injection Frameworks - Part 1 - Introduction

4.65/5 (26 votes)
12 Jun 2008CPOL4 min read 1   630  
An introduction to the dependency injection design pattern and frameworks, illustrated by a simple example.

Background

In recent days, the concept of dependency injection or inversion of control is much talked about in the object oriented world of programming. I decided to give an introduction to this concept for people who want to understand this concept with little effort and use it effectively.

Introduction

So, what is dependency injection anyway? Simply put, it is the capability of a consumer to consume a component without knowing in advance the specifics/origins of the consumed component.

image_thumb1.png

Now, you would ask, what’s new about this? Isn’t this why we have interfaces? I will explain this more clearly by taking an example of a design pattern that is much closer to the dependency injection design pattern; that is object creation, or factory framework. Consider a typical Factory pattern, as shown in the figure below.

image_thumb2.png

There is a subtle difference between the Factory pattern shown above and the truly desired object oriented abstraction. The fact that the class factory actually knows about the consumed class (which implements the desired interface that was originally requested by the consumer) breaks this abstraction and the plug and play feature. This is exactly where the dependency injection framework comes in.

Motivation

The motivation for the dependency injection framework comes from the concepts of "Inversion of Control" and extensibility. Applications, nowadays, are providing more and more extension points to enrich the functionality of solutions. Extended plug-ins, in such cases, really take on the control from the container that hosts them in the first place (hence the term "Inversion of Control"). Hence, dependency injection enables abstraction of dependencies at design time from the dynamic binding at runtime. This way, extension points can be instantiated, injected as properties or in the constructor of the dependent object, with dynamic configuration. A great example of such an application is Eclipse.

Dependency Injection Frameworks

In the dependency injection framework, the consumer specifies a set of dependencies that it requires to be fulfilled in order to perform an operation. During runtime, a configuration / declarative effort is required to specify the consumable objects that can fulfill a set of dependencies. An assembler / runtime component can then perform the necessary binding prior to code execution, or notify failure via exceptions. The following figure depicts this behavior.

image_thumb3.png

Dependency injection frameworks was really made possible by new generation object oriented languages that support metadata access capabilities such as Reflection and dynamic code generation / loading. The idea, however, is much older, and can be seen in dynamic linked libraries, and even COM.

There are many frameworks that aid in dependency injection. I will discuss one of the major frameworks, known as Spring.NET. Spring.NET implements many proven design patterns that make building enterprise applications easier. But, I will just focus on the dependency injection part of Spring.NET.

A simple example of dependency injection using Spring.NET

Trust me, even sample examples that ship with Spring.NET aren’t simple. So, I decided to make a small startup example to demonstrate how we can use Spring.NET to solve the factory creation scenario discussed above.

For building this code, I used Visual Studio .NET 2008, along with Spring.NET binaries that I obtained from here.

I then created a sample console project called SpringDotNETExample, and added a reference to the Spring.Core assembly to the project (this assembly can be found in the bin folder of your Spring.NET installation directory; for me, it was c:\Program Files\Spring.NET 1.1.2\bin\net\2.0\debug\Spring.Core.dll).

The scenario is very simple. We have a generic interface ISayHello that has a string property SayHello, as follows:

C#
namespace SpringDotNETExample    
{     
    public interface ISayHello     
    {     
        String SayHello { get; }     
    }     
}

I then created a class WorldSayHello that implements ISayHello, as follows:

C#
namespace SpringDotNETExample    
{     
    public class WorldSayHello : ISayHello     
    {        
        public string SayHello     
        {     
            get { return "Hello Friend!"; }     
        }     
    }     
}

At runtime, I want to bind my configuration to create WorldSayHello as a concrete implementation for ISayHello. But, this mapping will be transparent to my main program which will use the Spring.NET assembler to request an instance of the mapped object. For this example, I would assume that the main program requests this object via the key “ISayHelloInterface” that must correspond to the mapping.

To create the mapping, I created a mapping in my application configuration file, app.config. Following are the contents of this file. I have bolded the interesting parts of this file, rest are just Spring.NET essentials that are less interesting.

XML
<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>    
<configuration>     
  <configSections>     
    <sectionGroup name=&quot;spring&quot;>     
      <section name=&quot;context&quot;    
        type=&quot;Spring.Context.Support.ContextHandler, Spring.Core&quot; />     
      <section name=&quot;objects&quot;     
       type=&quot;Spring.Context.Support.DefaultSectionHandler, Spring.Core&quot; />     
  </sectionGroup>     
</configSections>
  <spring>
    <context>
      <resource uri=&quot;config://spring/objects&quot;/>
    </context>
    <objects xmlns=&quot;http://www.springframework.net&quot;>
      <description>An example that demonstrates simple IoC features.</description>
      <object name=&quot;ISayHelloInterface&quot; type=&quot;SpringDotNETExample.WorldSayHello,
          SpringDotNETExample&quot;/>        
    </objects>
  </spring>     
</configuration>

Now, my program simply requests the object mapped to the key ISayHelloInterface to obtain an implementation of the ISayHello interface. Notice that the mapping can be changed without compiling the code. This can provide immense versioning capabilities. Following is my main program:

C#
using System;   
using Spring.Context;    
using Spring.Context.Support;
namespace SpringDotNETExample   
{    
    class Program    
    {    
        static void Main(string[] args)    
        {    
            IApplicationContext ctx = ContextRegistry.GetContext();    
            ISayHello hello = (ISayHello)ctx.GetObject(&quot;ISayHelloInterface&quot;);    
            Console.WriteLine(hello.SayHello);    
        }    
    }    
}

Running the program yields the following output :)

Hello Friend!   
Press any key to continue . . .

In my next article, I will discuss some more advance concepts in dependency injection, such as constructor injection. So, stay tuned!

History

  • Initial article - Thursday, June 12, 2008.

License

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