Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / C#

Using the Dependency Injection Pattern and Unity Containers with a Service Locator

Rate me:
Please Sign up or sign in to vote.
4.18/5 (11 votes)
5 Feb 2009CPOL6 min read 92.5K   37   3
Using a Unity Container or a Service Locator.

Introduction

In this article, we will see how to leverage Dependency Injection, Unity Containers, and Service Locators in your code for better scalability and testability.

Where do I start?

You'll need to download the Unity Application Block and the Service Locator from Microsoft.

Unity with Service Locator

From MSDN, “The Unity Application Block (Unity) is a lightweight, extensible dependency injection container.”

What is a Dependency Injection Container anyway?

For those of you who work on projects that follow a composition model over an inheritance model, containers are an ideal solution. A DI container, sometimes referred to as an Inversion of Control container or IOC container, is a container which “contains” and manages some type of object abstraction. The container takes care of instantiations, injecting dependencies, sometimes singleton lifetime management, as well as supplying “cross-cutting” services to objects being hosted inside the container.

From MSDN, “A cross-cutting service is defined as a service that is generic enough to be applicable across different contexts, while providing specific benefits. An example of a cross-cutting service is a logging framework that logs all method calls within an application.”

What is Inversion?

Inversion refers to inverting or “filpping” the way you think about your program design in an object oriented way. If your programming model interrupts the normal control flow, then you are probably using some sort of Inversion principal in your design.

Inversion can occur in Event-driven programming in the case of, say, custom ASP.NET User Controls. The “bubble up” of events from the User Control to the page can be thought of as a form of Inversion because it “reverses” the normal control flow, which would be the page calling the control and “observing” an event on the custom control by registering an event handler on the calling page.

Another form of Inversion is Dependency Injection. This is one of my favorite patterns, and was first coined by Martin Fowler. Basically, if an object needs access to another object (we’ll call it service for this text), the object takes on the task of acquiring the service in one of three ways:

  • Interface injection: The service provides an interface which consumers must implement. The interface exposes specific behaviors at runtime.
  • Setter injection: The dependent object exposes a “setter” method to inject the dependency.
  • Constructor injection: Dependencies are injected through the class constructor.

Inversion takes yet another form with the use of the Factory pattern. In the Factory pattern, the Factory takes care of any initialization steps for that object. The factory also takes care of producing different kinds of objects for the Dependent object. The Dependent object, therefore, no longer has to depend on each type of concrete object, knowing how to construct each one, and instead, looks to the Factory to take care of these repetitive tasks for it, thereby inverting control.

Why not just use a Factory?

Configuration: A container’s services can be created either declaratively (via configuration files) or using .NET bases attributes. Your consuming objects don’t need any knowledge of how to construct services.

The number types is often hardwired into Factories, while Containers can produce any number of different types.

Containers provide services which can be used across various applications in an enterprise without having to embed specific logging into an application. In .NET, for instance, the way Containers can manage lifetimes for you, enables you to create your Containers on application start and make them available application wide.

Unit Testing. The loose coupling is ideal for Unit Testing. If you use composition in your programming model, you have the option of creating test containers with mock data which your objects can execute against, instead of depending on hitting production systems..

Unity Container example:

Creating a basic Unity Container is quite simple. You need the class that you want to create and the Interface it provides. In this case, we want our Unity Container to hold a FooModel. FooModel provides several public methods through the IfooModel interface. Creating our Unity Container goes something like the example below:

C#
/// <summary> 
/// Handles the initialization of the test cases. 
/// </summary> 
[TestInitialize] 
public void Init() 
{ 
    IUnityContainer container = new UnityContainer() 
        .RegisterType<IFooModel, FooModel>(); 
    this.unityContainer = container; 
    this.model = this.unityContainer.Resolve<IFooModel>(); 
}

The example above will be available to each of the test methods in our test class.

Say, however, that we want our Container to manage a Singleton for us and the FooModel now takes a dependency on the constructor. The example below will turn our FooModel into a Singleton and will handle injecting dependencies for us.

C#
/// <summary> 
/// Handles the initialization of the test cases. 
/// </summary> 
[TestInitialize] 
public void Init() 
{ 
    /// Makes FooModel a singleton 
    IUnityContainer container = new UnityContainer().RegisterType<IFooModel, 
                                    FooModel >(new ContainerControlledLifetimeManager()); 
    /// Inject a FooDependencyObject. 
    container.Configure<InjectedMembers>().ConfigureInjectionFor<FooModel>(
              new InjectionConstructor(new FooDependencyObject())); 
    this.unityContainer = container; 
    this.model = this.unityContainer.Resolve<IFooModel>(); 
}

Simple, and you can see that the Resolve method will produce our Foo Singleton.

There are two types of lifetime managers, ContainerControlledLifetimeManager and ExternallyControlledLifetimeManager.

ContainerControlledLifetimeManager will implement a Singleton, returning the same instance of the object each time you call Resolve or ResolveAll.

ExternallyControlledLifetimeManager will return the same instance of the object; however, the container holds a “weak reference” to the object. Basically, the object is subject to garbage collection when it goes out of scope.

If you don’t name a lifetime manager, you will get a new object each time.

What is a Service Locator all about?

Well, it’s a Container too, but it doesn’t instantiate anything or manage any lifetimes for you.

For those of you who work on projects that favor inheritance over composition, it offers you decoupling with concrete types. It doesn’t handle instantiation or manage lifetimes for you, but its’ still better than a Factory.

Say, for example, you have a class that depends on two different services whose type is specified at design time. Your dependent class must know how to construct each of those services.

A Factory still won’t work because Service A and Service B are two different types of objects.

What a Service Locator does is hold a reference to Service A and Service B for you so your dependent class only needs to know how to call the Service Locator and pass in the type of the Service it needs.

Your dependent class calls the Service Locator, passing in the type of the Service it needs and the Service Locator will return an instance of the Service.

You can actually combine the Service Locator and the Unity Container by putting a Unity Container inside a Service Locator. It’s not the most practical thing I’ve heard of, but you could run into a situation where you find yourself with two separate Unity Containers sometime in the future.

Can I put my Unity Container in a Service Locator?

I actually used this approach when I was refactoring using Test Last Development. I knew that my classes would be refactored for composition from inheritance, and that I would use dependency injection at some point, but I wasn’t quite sure how many things I would inject, so I just injected a Service Locator with a Unity Container full of all of my services objects inside. Next, I made the tests pass, and finally, I was able to gradually abstract the data, create the interfaces, and then just got rid of the Service Locator altogether.

Refactoring is an entirely different subject, and you can read my page on Test Last Development if you would like more information on my take.

So what does a Service Locator look like?

Well, first, the bad news is that if you want to inject a Unity Container, you have to create a custom Service Locator. Yep, you have to create your own by inheriting from ServiceLocatorImplBase. Here’s an example of a Service Locator. You’ll need to override the methods, as needed, in your implementation.

C#
using Microsoft.Practices.ServiceLocation; 
using Microsoft.Practices.Unity; 
public class MyServiceLocator : ServiceLocatorImplBase 
{ 
    private IUnityContainer container; 
    public MyServiceLocator(IUnityContainer container) 
    { 
        this.container = container; 
    } 
    protected override object DoGetInstance(Type serviceType, string key) 
    { 
        return this.container.Resolve(serviceType, key); 
    } 
    protected override IEnumerable<object> DoGetAllInstances(Type serviceType) 
    { 
        return this.container.ResolveAll(serviceType); 
    } 
}

Next, you’ll need a Unity Container to add to the service locator.

C#
/// <summary> 
/// Handles the initialization of the test cases. 
/// </summary> 
[TestInitialize] 
public void Init() 
{ 
    /// Makes FooModel a singleton 
    var container = new UnityContainer() 
        .RegisterType<IFooModel, FooModel >(new ontainerControlledLifetimeManager()); 
    /// Inject a FooDependencyObject. 
    container.Configure<InjectedMembers>().ConfigureInjectionFor<FooModel>(
              new InjectionConstructor(new FooDependencyObject())); 
    var myServiceLocator = new MyServiceLocator(container); 
}

That’s it, your Service Locator has a Unity Container inside.

If you want an instance of a class in your Unity Container, you just ask your Service Locator for it.

C#
this.myServiceLocator.GetInstance<IFooModel>().DoStuff(); 

You can read more about this at my website: http://caloia.wordpress.com/.

License

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


Written By
Software Developer (Senior) Microsoft
United States United States
Chris Aloia lives in the Seattle area and works as a Senior Software Development Engineer for Microsoft Corporation.

Comments and Discussions

 
GeneralNice article Pin
Sohel_Rana25-Sep-09 3:09
Sohel_Rana25-Sep-09 3:09 

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.