Dependency Injection Tools and Inversion of Control - Applying Domain-Driven Design and Patterns

Dependency Injection Tools and Inversion of Control - Applying Domain-Driven Design and Patterns

by David Hayden ( Sarasota Web Developer )

 

Kudos to Erik Dornenburg, who finally made the light go off in my thick brain as to the value of Dependency Injection Tools. Erik is a guest author in Jimmy Nilsson's new book, Applying Domain-Driven Design and Patterns, and he wrote the most excellent chapter, called Inversion of Control and Dependency Injection. Here is how it happend :)

 

Service Locators and Factories

During some down time this week I started updating some CodeSmith Templates that create an administrative backend to a database. The templates work fine, but I thought I would update them to use ASP.NET Master Pages and Generics. While going through the code, I came across my typical use of Service Locator and Factory Classes that offer a bit of loose coupling and testability of the data access code. Here is an example of the Factory Class, for example, that creates the Data Access Objects used in the application:

 

public class DAOFactory
{
    public static T Create<T>()
    {
        IDatabase db = Registry.Fetch<IDatabase>();
        T dao = Registry.Fetch<T>();
        dao.Database = db;
        return dao;
    }
}

 

You would use the code like this:

 

ICustomerDAO dao = DAOFactory.Create<ICustomerDAO>();

 

The Registry Class used in the Factory is essentially a Service Locator. The Service Locator reads a name-value collection of concrete classes at runtime that implement the services needed by the application. Thus, when you call

 

Registry.Fetch<ICustomerDAO>();

 

it is essentially retrieving the concrete class that implements ICustomerDAO, which is set in the configuration file or changed at runtime. More than likely this will just be CustomerDAO :)

Additionally, the Data Access Objects are dependent on an IDatabase Class, which is responsible for the actual database calls and specific for each database. Although in this case I have only written one class that implements IDatabase, SqlServerDatabase, the idea is that you could have versions for Oracle, MySql, etc. This IDatabase dependency gets injected into the DAO via a setter in the Factory Class as mentioned above:

 

IDatabase db = Registry.Fetch<IDatabase>();
T dao = Registry.Fetch<T>();
dao.Database = db; // Inject Dependency

 

All of this is pretty standard use of good object-oriented principles and design patterns to keep your application loosely-coupled, offer testability, and provide pluggability. But, this is stuff I don't really need to do, because Dependency Injection Tools already do this for me and do a better job - DOH!

 

Dependency Injection Tools

Around the same time that I started updating the CodeSmith Templates, I also promised myself that I would look at Jeremy Miller's StructureMap that he has been talking about off and on via his blog. My reason for doing so was mainly to better understand what he felt so passionate about to create and talk about in several posts. As it happens, StructureMap just happens to be a Dependency Injection Tool, one of several for the .NET Framework.

Now the concept of Dependency Injection is not new, although I seem to hear it more and more these days. It essentially means that objects don't go out and get other objects that they depend upon; instead the dependent objects are given ( injected ) to them. The perfect example is my DAOFactory above. The Data Access Object doesn't go out an get the IDatabase Service it is dependent upon, I populate it via a property setter in the Factory.

 

dao.Database = db; // Inject Dependency

 

This is great for testability, because normally when I build and test these classes I will create test stubs that read data from an xml file, for example, so that I am not dependent on a database or other external process.

Now what I had not realized is that a Dependency Injection Tool is essentially a Service Locator and Factory in one. Either during runtime or in a configuration file, you can specify all the services ( StructureMap calls these Plug-In Families ) and their concrete implementations ( Plug-Ins ) and their dependencies.

By using StructureMap, I can remove my Factory and Service Locator Classes completely from the application. I map the services and dependencies in a separate configuration file, called StructureMap.config, and one call does everything:

 

ICustomerDAO dao = (ICustomerDAO)ObjectFactory.
GetInstance(
typeof(ICustomerDAO));

 

Behind the scenes, StructureMap finds the appropriate implementation of ICustomerDAO and injects it with the appropriate implementation of IDatabase which is also injected with the appropriate connection string. It's a thing of beauty and I feel really late to the show :)

 

Conclusion

If you haven't embraced a Dependency Injection Tool in your application, I highly recommend doing so. It makes your applications far more loosely coupled and avoids one from having to wire up all this stuff yourself using Factories, Registries, and Service Locators.

By no means am I pushing StructureMap. There are other tools for the .NET Framework: Spring.NET, Castle Windsor, ObjectBuilder, etc. I've downloaded a number of them and will be trying them out in the upcoming weeks.

 

Resources:

 

Source:  David Hayden ( Sarasota Web Developer )

Filed: Design Patterns, .NET Tools

 

posted on Friday, July 21, 2006 1:16 PM

Main

News

Green Tea

.NET Development

Enterprise Library

Patterns & Practices