Dependency injection is a technique for building loosely coupled applications. It decouples the dependencies between objects and abstracts their connections. Let's consider an example of a data access component that holds a Logger member that log messages to a database. The component in question has a dependency on the Logger implementation. When we apply dependency injection principal we will use an interface of an ILogger as the member of the data access component and inject the relevant ILogger implementation using a dependency injection container. Doing so will make sure that the data access component has no dependency on the Logger implementation and make this component more loosely coupled. With dependency injection we can achieve a plug-in architecture with minimum dependencies between application objects. It also helps to make our application more testable since in tests we can inject a fake implementation instead of calling the original object. An example for using dependency injection can be seen in the following figure which is taken from Martin Fowler's site:
In this figure the MovieLister needs an implementation of MovieFinder interface. The real implementation which is the MovieFinderImpl isn't known to the MovieLister at all. The role of the Assembler (the DI container) is to perform the dependency injection and inject the MovieFinderImpl instead of the MovieFinder interface during runtime using information that is known only to it (for example a configuration file).
There are three known options in order to perform dependency injection:
- Constructor Injection: When constructing a new instance of an object we inject the dependencies.
- Setter Injection: the component exposes a setter method or property which we will inject a dependency to it.
- Interface Injection: we create an interface that components must implement in order to be injected during runtime.
In the .Net ecosystem there are many dependency injection components. The main ones include Unity, Spring.NET, Ninject, MicroKernel/Castle Windsor and StructureMap. In this article we will focus on Unity to show how dependency injection can be implemented in practice.
What is Unity?
Unity is an application block that was shipped by the Microsoft patterns and practices team on 2008. Since then it was adopted as the core dependency injection component of Enterprise Library and other components and applications. Unity is described as a lightweight, extensible dependency injection container. It enables constructors, properties or method calls injections. The main reason to use it is to design and build loosely coupled applications. Using dependency injection will make the application you write more flexible to changes and more maintainable.
Why to use Unity?
- It simplifies the object creation process.
- Abstractions of requirements – dependencies are specified during runtime or by configurations files.
- Increased flexibility by deferring component configuration to third party container.
- Service location capability – clients can store (or cache) the dependency injection container.
When to Use Unity?
- You have dependencies between objects.
- The dependencies are complex and you need a way to abstract them.
- You want to be able to change your dependencies at runtime.
- You want to use constructors, properties or method calls injections.
Setting Up a Unity Container
In order to start using Unity the first thing you will have to do is to set up a Unity container. The Unity container is the basic and main component of the Unity ecosystem. The container will hold all of your registered mappings and will help you to resolve them during the application execution.
There are two ways to set up the Unity container:
- Using XML format configuration file which use the Unity schema.
- Using the container configuration API to configure the container.
The Unity container has two main methods to register types:
RegisterType – The type is registered in the container and the container is responsible to initialize it when it is needed.
RegisterInstance – An instance of a type is registered in the container with a lifetime which you can include (for example a singleton lifetime). During the registered lifetime the container will return the instance when it is needed.
After the registration of the types you will be able to use the Unity container's Resolve method in order to resolve a registered type. The following example shows how to register a mapping between an interface of ILogger to a FileLogger concrete class:
In order to register a mapping from an ILogger interface to more than one concrete class you can use a name for each concrete class which is shown in the following example:
When you register names it will help you to provide more than one implementation of the interface in your application.
In some cases you already have an existing object and you want to use it. The Unity container enables you to register an instance with the
RegisterInstance method. When registering an instance, the default container behavior will be to return the same instance every time it is needed when the
Resolve method is called. The object will act as a singleton. Here is an example of how to use the
In the example, I pass the FileLogger instance to the
RegisterInstance method which will make sure that when the ILogger is resolved this instance will be returned by the container. The singleton behavior can be overridden by sending a second parameter of a LifetimeManager implementation to the
Resolving a Dependency
After registering the types in the Unity container you'll probably want to use them. How do you do it? The answer is the Resolve method. The following example shows how to use the Resolve method:
As you can see the Resolve method will return an ILogger which will be of type FileLogger under the hood. The Unity container will instantiate the FileLogger and will return a new instance of that class as an ILogger interface. If you registered more than one concrete class you can use the
Resolve method's overload that gets a name of the mapping to return the relevant mapped class or use the
ResolveAll method to get back an IEnumerable collection of all the registered types:
Dependency injection isn't a concept that will disappear one day. The dependency injection concept helps to make your applications more loosely coupled and more extensible. In this article I explained what is the concept and what is Unity application block. I also showed you the basics of using Unity which are the register and resolve methods.
Gil Fink, Microsoft MVP, is an expert in web development and Microsoft data platform. He works as a senior architect at Sela Group. He is currently consulting for various enterprises, architecting and developing web and RIA based solutions. He conducts lectures and workshops for developers and enter...
View complete profile here.
Please login to rate or to leave a comment.