Infragistics WPF controls

Dependency Injection and Inversion of Control Ioc With the Microsoft Unity Container

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));
        }
    }
}

 

AuthenticationService.cs

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

namespace UnityExample
{
    public class AuthenticationService
    {
        public AuthenticationService()
        {
            
        }

        internal void Authenticate(string userName, string password)
        {
            //Authentication logic goes here
            TextLogger logger = new TextLogger();
            logger.LogMessage("Login was successful");
        }
    }
}
 

Program.cs

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

namespace UnityExample
{
    class Program
    {
        static void Main(string[] args)
        {
            AuthenticationService authenticationService = new AuthenticationService();

            authenticationService.Authenticate();
        }
    }
}

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.

ILogger.cs

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

namespace UnityExample
{
    public interface ILogger
    {
        void LogMessage(string message);
    }
}

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.

Here is the updated AuthenticationService.cs

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

namespace UnityExample
{
    public class AuthenticationService
    {
        //the logger is now a class field
        private ILogger logger;   

        public AuthenticationService(ILogger implementation)
        {
            //The implementation is injected via the constructor
            logger = implementation;
        }

        internal void Authenticate(string userName, string password)
        {
            //Authentication logic goes here

            
            logger.LogMessage("Login was successful");
        }
    }
}

DBLogger.cs updated

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.

Download the source 

UnityExample.zip (723.64 kb)

Happy coding!

kick it on DotNetKicks.com



Comments (22) -

James Yoo
James Yoo
11/15/2012 10:48:50 AM #

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.

Buddy James
Buddy James
11/15/2012 12:04:23 PM #

I'm glad you enjoyed the post.

Thank you for reading!

James Yoo
James Yoo
11/15/2012 3:20:12 PM #

Would you care to do a version of this that uses a config file instead of a module?

Buddy James
Buddy James
11/15/2012 5:04:14 PM #

Yes.. I can do that...

Check back soon!

Thanks again for reading!

catch me on twitter @ http://www.twitter.com/budbjames

pkotak
pkotak
12/13/2012 5:02:43 AM #

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?

Buddy James
Buddy James
12/13/2012 7:54:57 PM #

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.

Please let me know if you have any more questions.

Thanks again for reading!

www.refactorthis.net/.../UnityExample.zip

pkotak
pkotak
12/15/2012 5:52:59 AM #

The link gives a 404 because the file has a double .zip postfix; however, managed to get the source files by browsing to www.refactorthis.net/downloads/UnityExample/
Thanks!

Buddy James
Buddy James
12/19/2012 8:13:28 PM #

Thanks for the heads up!  For what it's worth, I've fixed the download link.  I'm glad you were able to find it.  Thanks again for reading.

JOKe
JOKe
12/13/2012 2:33:26 PM #

Really ... no really ... Spring and Spring .net is so much better so much clearer and easier... Please dont loose time with this Unity thingy.

Buddy James
Buddy James
12/13/2012 8:00:06 PM #

Thanks for reading!

I've heard good things about Spring.NET but I haven't tried it.

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.

Thanks again for reading.

Donald Mafa
Donald Mafa
1/9/2013 12:27:52 AM #

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.

Buddy James
Buddy James
1/11/2013 12:11:55 PM #

Thanks for reading!

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.  

I hope this helps.

Buddy James

Ravi
Ravi
2/14/2013 1:14:36 AM #

I just love it and hopefully understand it quite well, I am new to asp.net, is there any book or site which will help to learn C# like you explained above, please mail me?

Buddy James
Buddy James
2/15/2013 2:42:12 AM #

I'm glad you enjoyed the article!

My favorite book on C# (and .NET for that matter) is Pro C# 5.0 and the .NET 4.5 Framework (Professional Apress) by Andrew Troelsen .

The first edition of the book that I ever bought was the version that covered the CLR 1.1!

It is a very great resource for learning C# and the .NET framework.

As far as learning Ioc/Dependency Injection goes, I can personally recommend Dependency Injection in .NET by
Mark Seemann.  It's a great read!

Thanks for reading!!

Sankar
Sankar
3/13/2013 5:15:26 AM #

Thank you very much for the article.
Very neat and clearly explained

Buddy James
Buddy James
3/13/2013 7:25:28 PM #

Sankar,

I'm glad that you enjoyed the article.

I plan to write a more in depth article on dependency injection.

Stay tuned.

Thanks again,

Buddy James

Jeffrey
Jeffrey
3/23/2013 1:53:10 AM #

Hey thanks for clear walkthrough. : )

Buddy James
Buddy James
3/28/2013 12:02:08 PM #

No problem Jeffrey.

Thanks for reading!

Buddy James

Anu Tripathi
Anu Tripathi
7/24/2013 6:22:37 PM #

Thanks for clear walkthrough, James. You mentioned above that you will have post the version of this that uses a config file instead of a module. Could you please share the link to that here?

Buddy James
Buddy James
7/24/2013 10:38:15 PM #

@Anu Thank you for reading!

I plan to start releasing an article each week.  I'll be sure to cover using the configuration file with Unity for my next article.

Thanks again,

Buddy

Andrew
Andrew
8/19/2013 8:19:35 PM #

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() ?

Buddy James
Buddy James
8/22/2013 2:57:59 AM #

@Andrew

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?

thanks for readying.

Pingbacks and trackbacks (3)+

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

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).  

Related links

Month List