What is Dependency Injection (and why you should care)?

There is much discussion around the new ASP.net MVC framework. Scott Guthrie has been writing a series of articles describing the functionality of the upcoming framework. I highly recommend looking at this soon to be released framework offering from Microsoft. One feature that I am happy to see is the ability to integrate the MVC framework with dependency injection containers such as Spring.net and Windsor. I plan to go over this integration capability in a future post but I like to start with a post discussing dependency injection in general.

The central idea behind dependency injection containers, also called Inversion of Control (IoC) containers, is to create flexibility in program architecture by removing the knowledge of dependency creation and configuration from the individual software components. For instance, I have a program that has a customer component whose responsibility is saving and retrieving customer objects. The customer component is a user of the validation component as well as the persistence component. Traditionally, I would have simply created new instances of these services from within my customer component:

public class CustomerComponent {

    private ValidationComponent validationComponent;

    private PersistenceComponent persistenceComponent;

    public CustomerComponent() {

        validationComponent = new ValidationComponent();

        persistenceComponent = new PersistenceComponent();

    }

    //use these two components

}

The problem with this implementation is that it ties my customer component to these two concrete implementations of its dependent services. Of course, a better way to this is to use some sort of factory pattern implementation. That code might look like this:

public class CustomerComponent {

    private ValidationComponent validationComponent;

    private PersistenceComponent persistenceComponent;

    public CustomerComponent() {

        validationComponent = MyFactory.Get("Validation");

        persistenceComponent = MyFactory.Get("Persistence");

    }

    //use these two components

}

This is much better than the first block of code because I am no longer tied to the concrete implementations, provided that ValidationComponent and PersistenceComponent are abstract implementations. However, I am tied to the MyFactory class implementation. This is where a dependency injection framework comes to the rescue. A dependency injection container allows me to define properties in my customer component class for each of the dependent components I need. When the container creates an instance of my customer component, those dependency properties I have created are automatically set with fully configured implementations.  In the code below, the CustomerComponent implementation has properties for the validation and persistence components, but no code to set these properties:

public class CustomerComponent {

    private ValidationComponent validationComponent;

    private PersistenceComponent persistenceComponent;

    public ValidationComponent Validation {

        get {return validationComponent;}

        set(ValidationComponent value) {validationComponent = value;}

    }

    public PersistenceComponent Persistence {

        get {return persistenceComponet;}

        set(PersistenceComponent value) {persistenceComponent = value;}

    }

    //use these two components

}

If I am using C# 3.0, I can take advantage of the new property syntax and my class will trim down some:

public class CustomerComponent {

    private ValidationComponent validationComponent {get;set;}

    private PersistenceComponent persistenceComponent {get;set;}

    //use these two components

}

The dependency injections frameworks will all vary slightly on what happens from here but they all have a lot in common.  Spring.net, Windsor, and StructureMap all have xml configuration files that allow you to specify the .Net System.Type and give a name to each  of your components.  They also have the ability to set properties on your components, or even set private field values in certain cases.  The values of these properties can be standard  .Net data types or they can also be other objects that have configured in the container.

This was a very brief introduction to the concept of dependency injection and I am planning to write up more detailed descriptions on the details of using Spring.net, Windsor, and StructureMap soon.

Tags: , , ,