Design for Reusability

A well designed application should promote code reuse whenever possible. Code reuse can save you time and money by allowing you to use components from previous applications to solve common problems in new projects. The task of managing dependencies is one of the many concerns a developer faces when designing for reusability. Dependencies are any classes that a particular class must directly instantiate and use in order to accomplish a task. As a rule of thumb, it's good object oriented programming practice to code to an interface rather than a concrete implementation. This will make your code flexible and built for change.

An example of a dependency

You've been tasked to write a console application. The application requires that the user authenticates before using any of the features and there is a requirement that all successfully log-ins are logged to a text file. Here is the code for the example.

TextLogger.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UnityExample
{
public class TextLogger
{
public void LogMessage(string message)
{
//Code to write the message to a text file....
Console.WriteLine(string.Format("Logging the message to a text file: {0} ", message));
}
}
}

This is a basic example for demonstration purposes only. Now, as you can see in the AuthenticationService Authenticate method we are instantiating an instance of the TextLogger class. So now a few weeks pass by and the customer wants you to log to a database instead of a text file. So you create a new class.

DBLogger.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UnityExample
{
public class DBLogger
{
public void LogMessage(string message)
{
//Code to write the message to a database....
Console.WriteLine(string.Format("Logging the message to a database: {0} ", message));
}
}
}

The AuthenticationService was dependent on the TextLogger and is now dependent on the DBLogger class. The current design requires us to change the AuthenticationService any time the customer requests a new type of logger. The same holds true for any unit tests that we write that uses a Logger class. As you can see the design promotes tight coupling because we are coding to a concrete implementation which is not very flexible.

Introducing an interface

As we can see, both logger classes have one method called LogMessage. They share the same interface. This is a perfect example of an instance in which we should code to an interface. So we start by creating an interface that matches the two logging classes.

Now we could simply change the logger declaration in the AuthenticationService and be done with it, however, there are still some optimizations that can be achieved. For instance, currently the Logger declaration is a local variable inside of the Authenticate method. Imagine were to inject the ILogger as a parameter of the AuthenticationService constructor. This is a much more flexible design because the AuthenticationService only has knowledge of an ILogger. Since the implementation is injected via the constructor, the class is no longer tied to any one specific implementation.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace UnityExample
{
public class DBLogger : ILogger
{
public void LogMessage(string message)
{
//Code to write the message to a database....
Console.WriteLine(string.Format("Logging the message to a database: {0} ", message));
}
}
}

The Unity Container

The Unity container allows us to use code (or a configuration file) to associate an interface with a class. This is typically done during your application start up or the set up of your unit tests. You register your interface and class mappings. Then later when it's time to instantiate an instance of your objects, you ask the container to resolve an instance of the object that you need. The Unity container will perform an internal look up and it will resolve any dependencies that your object's constructor depends on.

I prefer to register my interface/class mappings in a class that I call a module. When my application starts I load all modules to prepare the container to resolve all of the objects that I will need. This abstraction allows you to easily switch an interfaces implementation at run time providing a high level of flexibility to your code. Here is a brief example of how to use the Unity container. You will need to download the Unity assemblies from nuget or from the Microsoft patterns and practices Unity Application block site.http://unity.codeplex.com/

LoggingModule.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;
namespace UnityExample
{
public class LoggingModule
{
IUnityContainer _iocContainer;
public LoggingModule(IUnityContainer container)
{
_iocContainer = container;
}
public void Init()
{
//Add any logic here to look in a config file, check a property
//or any other condition to decide which implementation is registered.
//register the database logger to the ILogger interface
_iocContainer.RegisterType(typeof(ILogger), typeof(DBLogger));
}
}
}

Updated Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;
namespace UnityExample
{
class Program
{
private static IUnityContainer _iocContainer;
static void Main(string[] args)
{
//create our container
_iocContainer = new UnityContainer();
InitializeModules();
//the container knows how to create an AuthenticationService object
//as well as what type of ILogger it takes because we registered
//the required class in the loggerModule.
var authenticationService = _iocContainer.Resolve<AuthenticationService>();
authenticationService.Authenticate("username", "password");
Console.WriteLine("press any key");
Console.ReadKey();
}
private static void InitializeModules()
{
//pass the container to the module
//so when we register the types we can resolve them
var loggingModule = new LoggingModule(_iocContainer);
loggingModule.Init();
}
}
}

This is a very basic introduction to Unity but you I hope that you can see the possibilities when you program to interfaces and let the container take control of object creation. You could extend this example to create a ModuleInitializer class that takes the modules that need to be initialized.

The bottom line is

Program to interfaces

Inject dependencies via the constructor

Register your dependency interfaces to the desired class in the unity container. You can use a module approach if you so choose.

As long as your interfaces are mapped to classes in your container, the container can resolve any dependencies that your object requires when instantiated.

FANTASTIC simple example, thank you so much!! I've been wanting to play around w/ IoC for a while but don't have lots of time dealing with complex examples. I'm gonna practice other examples of this and try to do a quick lunch & learn for some of our developers.

Great article, very useful for me, attempting to use Unity and DI for the first time in a real project. However, I cannot open the download source in VS2010, despite my attempts to hack the solution file. Any chance you can make the download openable in VS2010?

Thanks for reading. I've made a zip file of all of the source files by themselves. You can create a blank project and add the source. Remember to download and add the Unity reference or use Nuget package manager.

It's true there are many alternatives to Unity for dependency injection. These include Ninject, Castle Windsor, StructureMap, Autofac, and more.

I personally chose Unity because it's simple, does everything I've needed it to do, and it's a part of the Microsoft patterns and practices suite so it integrates well with other Microsoft products like Prism etc.

I suggest that if you are learning try all of them if you can. It will only make you a better programmer and you'll be able to use the container that feels right to you.

Hi, I just wanted to find out what you do using the modular approach in a scenario whereby you want to use both TextLooger and DbLogger classses within your project for different reasons, that is , do u register both types and how is the container able to resolve which one you which to use in its particular case. Please advise.

You can register multiple versions of the same base class or interface by specifying a name for each type. You then specify the name when resolving the instance that you need. I cover this in another post on Unity which can be found here www.refactorthis.net/.../...d-implementations.aspx.

Can you show the code for Program.cs before you go on to the Unity Container section? You change the constructor of AuthenticationService to take in a ILogger parameter but do not show how you initialize the call to the class. Do I pass in a new TextLogger() / new DBLogger() ?

That's the point of Dependency Injection. DBLogger Implements the ILogger interface. AuthenticationService takes an ILogger as a constructor param. ILogger is therefore a dependency of AuthenticationService. So once we register the ILogger interface with the Unity container then we use the container to resolve an instance of the AuthenticationService. Since the container knows that ILogger is DbLogger, the container will instantiate a new AuthenticationService and it will automatically inject the DbLogger dependency into the constructor. There is no need to use new to instantiate the AuthenticationService. Understand that this is a simple example of DI and that in a real application you would want to register all of your dependencies in one place (composition root) and call Resolve once to resolve an chain of dependencies to start your application. Does this answer you question?

Add comment

About the author

My name is Buddy James. I'm a Microsoft Certified Solutions Developer from the Nashville, TN area. I'm a Software Engineer, an author, a blogger (http://www.refactorthis.net), a mentor, a thought leader, a technologist, a data scientist, and a husband. I enjoy working with design patterns, data mining, c#, WPF, Silverlight, WinRT, XAML, ASP.NET, python, CouchDB, RavenDB, Hadoop, Android(MonoDroid), iOS (MonoTouch), and Machine Learning. I love technology and I love to develop software, collect data, analyze the data, and learn from the data. When I'm not coding, I'm determined to make a difference in the world by using data and machine learning techniques. (follow me at @budbjames).