Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C# 4.0
Article

The Inversion of Control Pattern

Rate me:
Please Sign up or sign in to vote.
4.56/5 (12 votes)
17 Apr 2011CPOL3 min read 36.9K   40   7
An understanding of "The Inversion of Control" Pattern

Introduction

A design pattern is a common solution for a common problem that has already been identified and tested. In other words, it’s a guideline that must be adjusted depending on the context, not used in a single, non-changing syntax.

The Inversion of Control Pattern

The term Inversion of Control (IoC) is a computer programming technique wherein the flow of the control of an application is inverted. Rather than a caller deciding how to use an object, in this technique, the object called decides when and how to answer the caller, so the caller is not in charge of controlling the main flow of the application.

This approach makes your code flexible enough to be decoupled. It can be unaware of what is going on in the call stack because the called object doesn't need to make any assumptions about what the caller is doing.

The Dependency Injection pattern is simply a concrete implementation of the IoC. Unfortunately, as Martin Fowler specifies in his book, there is a lot of confusion about these terms, because the common IoC containers available for languages such as Java or .NET are typically identified as IoC containers, but the techniques implemented in your code when you use these frameworks is the Dependency Injection pattern, which is just one of the available concrete implementations for IoC. For example, if you plan to work with a modularized WPF/Silverlight application using a well-known framework such as Prism, you might implement IoC using the Service Locator pattern and not Dependency Injection because you need a global IoC container available for all the modules. Imagine that you have a simple LogWriter concept that is used to write a log message either to a specific database table or to a specified file. You might depict this as shown in Figure 1.

Image 1

Using the Code

The UML diagram in Figure 1 is pretty clear; there’s an abstract BaseLogger class that exposes a WriteLog message, and two concrete classes that inherit from BaseLogger. These expose the method in two ways: one writes a log message to a database, the other to the file system. The following code shows the wrong way to use one of these concrete loggers— without applying an IoC implementation:

C#
static void Main(string[] args)
{
	/* 
	*
	*  Wrong way
	*/
	var firstLogger = new FileLogger();
	firstLogger.WriteLog("Some Text.");
	var secondLogger = new DatabaseLogger();
	secondLogger.WriteLog("Some other Text.");
	Console.ReadKey();
}

The biggest problem with this approach—not applying an IoC implementation—is that if you want to specify a different log at runtime, you’ll need to rewrite some code. That’s a huge architectural constraint. For example, suppose that you want to get rid of the FileLogger object. That’s not easy. You can’t simply eliminate it, because the application wouldn’t execute any more, or at least, you would need to modify and recompile it for it to continue working.

To solve the problem, the first step is to decouple the existing hierarchy by using an interface instead of the base abstract class, as illustrated in Figure 2. This way, you simply define a contract between a concrete log and its interface. Subsequently, to write a log message to a different location, you just need to render the interface in a specific way.

Image 2

The code that follows is a refactored version that uses an IoC approach to declare the type of logger to be used at runtime. This approach is still procedural, because it decides which logger to use, but at least it decouples the code, so this is a somewhat more flexible version of the custom writer.

C#
/// <summary>
/// Custom writer that can uses any log
/// </summary>
public sealed class Writer
{
	/// <summary>
	/// Accessor to the injected logger
	/// </summary>
	private ILogger logger;

	/// <summary>
	/// Initializes a new instance of the <see cref="Writer"/> class.
	/// </summary>
	/// <param name="logger">The logger.</param>
	public Writer(ILogger logger)
	{
		this.logger = logger;
	}

	/// <summary>
	/// Writes the specified message.
	/// </summary>
	/// <param name="message">The message.</param>
	public void Write(string message)
	{
		this.logger.WriteLog(message);
	}
}

At this point, you need something between the application and the logger that can resolve which logger to use at runtime. The following example uses procedural code to do that without using the Dependency Injection or the Service Locator patterns:

C#
static void Main(string[] args)
{
	// IoC without an IoC container
	var firstLogger = new FileLogger();
	//Injectin of a specific logger
	var writer = new Writer(firstLogger);
	writer.Write("Log for the File system.");
	Console.ReadKey();
}

Points of Interest

An alternative solution would be to implement the Dependency Injection or the Service Locator.

Image 3

History

  • 16th April, 2011: Initial version

License

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


Written By
Architect
India India
I spent some time working as a programmer and computer developer for several IT companies. I gained a lot of knowledge and experience in the process, and met some very supportive people in the industry. In May 2000' I joined LBS College for Higher studies.

I enjoyed my studies as much as academic studies can be enjoyed. I feel that I depend my understanding of computers because of them. The LBS College gives his students a high level of studying, but my main problem with it is that its tests are sometimes completely out of sync with the material that is learned, too long and/or too hard, and so students receive low grades and are frustrated. This is especially demotivating considering the fact that studying there is a lot of work.

Comments and Discussions

 
GeneralMy vote of 5 Pin
I A Khan19-Apr-11 18:44
I A Khan19-Apr-11 18:44 
GeneralMy vote of 5 Pin
Oshtri Deka19-Apr-11 8:33
professionalOshtri Deka19-Apr-11 8:33 
GeneralMy vote of 4 Pin
xondokan19-Apr-11 3:46
xondokan19-Apr-11 3:46 
GeneralDependency Injection? Pin
Richard James Moss18-Apr-11 21:32
professionalRichard James Moss18-Apr-11 21:32 
GeneralRe: Dependency Injection? Pin
AbhishekGoenka19-Apr-11 1:14
AbhishekGoenka19-Apr-11 1:14 
Thanks for your comments. Do you want me to elaborate more? If yes, which topic
GeneralRe: Dependency Injection? Pin
Richard James Moss19-Apr-11 2:58
professionalRichard James Moss19-Apr-11 2:58 
GeneralRe: Dependency Injection? Pin
AbhishekGoenka19-Apr-11 3:26
AbhishekGoenka19-Apr-11 3:26 

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

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