The Microsoft patterns & practices group has released its Dependency Injection container called Unity or the Unity Application Block. Developers can now create loosely coupled applications that are extensible using this lightweight container.
InfoQ had the opportunity to talk with Chris Tavares, the lead developer of the Unity project.
Rob Bazinet (RB): So, Chris, tell us who you are and how are you involved in Unity?
Chris Tavares (CT): My name is Chris Tavares. I’m a senior software developer in Microsoft’s patterns & practices group. I am currently the lead developer on Enterprise Library 4 and the Unity Application Block. I also wrote the vast majority of the Unity code, so Unity is pretty much my fault. I’ve been at patterns & practices for a little over two years. Previous to coming to Microsoft, I’ve bounced around the industry doing contracting, shrinkwrap development, and even a little bit of embedded software waaay back in the 90’s.
RB: What is the Unity Application Block?
CT: Unity is a Dependency Injection (DI) container. The standard article describing DI is from Martin Fowler[0]. As a quick summary, a DI container is a tool you can use to support building highly decoupled software. The DI container takes care of the details of which objects are interconnected, so you can build each one independently. This has a big impact for both testability and flexibility of the resulting code.
For example, in a banking system, you may have an object that manages account transfers. This object needs to get hold of the individual account objects, plus there’s also security rules and auditing requirements. A common implementation could look something like this:
public class AccountTransfer
{
public void TransferMoney(int sourceAccountNumber, int destAccountNumber, decimal amount)
{
Account sourceAccount = AccountDatabase.GetAccount(sourceAccountNumber);
Account destAccount = AccountDatabase.GetAccount(destAccountNumber);
sourceAccount.Withdraw(amount);
destAccount.Deposit(amount);
Logger.Write("Transferred {0} from {1} to {2}", amount, sourceAccountNumber, destAccountNumber);
}
}
Granted, this is pretty terrible code (no transaction management, for example), but work with me here. ;-)
This is pretty straightforward, but it’s also highly coupled to its environment. The calls to the global AccountDatabase class means that you can’t even compile this by itself, let alone test it. And what happens if the accounts are from two different banks? Similarly, the global Logger means that you cannot use this class in absence of not just a logger, but that specific global logger class. This results in a lot of pain when trying to write unit tests, and longer term it greatly limits the flexibility.
The principle of Separations of Concerns says my class shouldn’t be doing multiple things. Here, the class violates it, as it’s hard wired not just the details of how to transfer money, but also about how to get accounts out of the database, and how to write logging message. To restore that flexibility, those concerns should be in separate objects, which are then passed into the object that uses them, like this:
public class AccountTransfer
{
private IAccountRepository accounts;
private ILogger logger;
public AccountTransfer(IAccountRepository accounts, ILogger logger)
{
this.accounts = accounts;
this.logger = logger;
}
public void TransferMoney(int sourceAccountNumber, int destAccountNumber, decimal amount)
{
Account sourceAccount = accounts.GetAccount(sourceAccountNumber);
Account destAccount = accounts.GetAccount(destAccountNumber);
sourceAccount.Withdraw(amount);
destAccount.Deposit(amount);
logger.Write("Transferred {0} from {1} to {2}", amount, sourceAccountNumber, destAccountNumber);
}
}
This gets us closer. Now we don’t depend on external global objects, just on the instances passed in the constructor. This class can now be tested in isolation, and can even talk to different banks simply by passing in a different implementation of IAccountRepository.
However, now there’s a new cost. The creators of AccountTransfer now have to know how to create the needed dependent objects. What account repository do you use? Which logger? If these are set up in configuration, for example, now you’ve got code that’s dependent on your configuration everywhere, and you’re back at square one.
That’s where the Dependency Injection container comes in. It is a smart object factory. You tell the container how to resolve the dependencies of a particular object. Using Unity, for example, you could configure the container like this (using the API, there’s also support for external configuration files):
IUnityContainer container = new UnityContainer();
container.RegisterType<IAccountRespository, ContosoBankRepository>();
container.RegisterType<ILogger, DatabaseLogger>();
What this does is tell the container “If any object we resolve has a dependency on an instance of IAccountRepository, create a ContosoBankRepository and use that. If anyone needs an ILogger, give them a DatabaseLogger.” Now, you can ask the container to give you an instance of an object that has dependencies, like this:
container.Resolve<AccountTransfer>();
The Resolve call tries to create an instance of AccountTransfer. The container sees that the constructor requires an IAccountRepository and an ILogger, so it creates those (using the concrete types previously specified) and passes them to the constructor. This use of the container centralizes all the wiring of your application. This provides (typically) a single place in your application that deals with hooking objects together, and frees the individual objects of the responsibility for construction of object graphs. The resulting flexibility really pays off both in testability and flexibility. And if your dependencies change as your classes evolve, that doesn’t impact the creation of those objects, just the configuration of the container.
RB: Is Unity part of the Enterprise Library or does it stand on its own? There was some information I had read in the past that Microsoft Dependency Injection Block would be released as part of Enterprise Library 4.0.
CT: Unity stands on its own. Enterprise Library 4 is build on top of parts of Unity, and you can use Unity to access the functionality of Enterprise Library.
A small bit of history should hopefully clear up the confusion. Back when Enterprise Library 2 and the Composite UI Application Block (CAB) were released, under the hood of both of them was a small library called ObjectBuilder. ObjectBuilder was a framework which was used to build Dependency Injection containers. Both CAB and Enterprise Library consumed OB, but OB was its own independent thing that was later shipped separately[1].
Part of Unity is an updated version of ObjectBuilder. Enterprise Library 4 continues to use ObjectBuilder the way it did before: to read configuration and build up the appropriate Enterprise Library objects. We are also introducing a new way to access the Enterprise Library functions by resolving them directly through a container, rather than having that mechanism hidden. Scott Densmore’s got a blog post[2] that goes into more detail about what we’re planning there.
So, to reiterate: Unity is a standalone block. Enterprise Library uses parts of Unity or can be used with Unity. To save downloaders trouble, Enterprise Library includes the Unity binaries, so if all you care about is using Enterprise Library you’re good to go without any other stuff to install.
RB: Under what circumstances would a developer choose to use Unity?
CT: The first question to decide is if you want/need to do dependency injection. If so, I think Unity is a good choice, but we also suggest looking at the other containers in this space. Scott Hanselman has started a list of .NET DI container projects[3].
RB: How is Unity different than other DI containers and how does it stack up against them?
CT: Speaking from the patterns & practices pulpit, I have to be very careful on questions like this. I don’t want to give the impression of either endorsing or discouraging people against using outside projects. We strongly recommend that everyone evaluate their options and choose the container that meets their needs best, either Unity or one of the existing open source projects.
RB: There are quite a few DI containers already, what was the motivation by your team in creating Unity?
CT: Patterns & practices has been giving guidance around dependency injection for a while now. CAB, Mobile client Software Factory, Smart Client Software Factory, Web Client Software Factory, and Enterprise Library have all used DI in various ways. That last word is the killer: “various”. Each project, although they were all build on ObjectBuilder, did DI differently and incompatibly. Having an explicit, fully featured container that we can use unencumbered allows us to provide better guidance around DI and container based architectures.
There are other reasons as well. We have customers that will not touch open source software for whatever reason. Having a DI container from Microsoft makes them feel safer and lets them get the advantages. It also puts them in a good position to later switch containers if they wish.
Another goal is to raise the profile of Dependency Injection both inside and outside of Microsoft. Having a container from Microsoft helps promote DI both to the general Microsoft .NET developer community and internal Microsoft developers as well.
RB: What would you suggest is the best way for a developer or team to get started with Unity?
CT: Grab the download, install it, read through the docs, and take a look at the simple quick starts we shipped.
RB: Are there any quick starts available for Unity with best-practice and sample code?
CT: We have a small example of a Windows Forms application (the Stoplight Simulator) that uses the container to inject services. It’s pretty small and quite approachable. Versions are included in C# and VB.NET.
RB: What are the future plans for Unity?
CT: Nothing is set in stone, of course. My personal goals are to add a few more features (the ability to intercept method calls is highest on the list), and get future patterns & practices assets to standardize on container based architectures. A better configuration file system would be nice.
In the longer term, I’d love to get some or all of these concepts into the core platform in a reasonable way.
RB: Chris, thank you for your time today and the great information on Unity.
Taken from the Unity web site, Unity is:
The Unity Application Block (Unity) is a lightweight, extensible dependency injection container. It facilitates building loosely coupled applications and provides developers with the following advantages:
- Simplified object creation, especially for hierarchical object structures and dependencies
- Abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns
- Increased flexibility by deferring component configuration to the container
- Service location capability; this allows clients to store or cache the container
Developers should look at the Introduction to Unity to get a good overview of getting started with Unity. Additional information about the Unity Application Block can be found at the Patterns and Practices web site and can be downloaded from the CodePlex web site. Readers can follow Chris at his blog. Dependency Injection coming to the Enterprise Library 4 was covered on InfoQ in December 2007, called Microsoft Enterprise Library 4.0 will get a dose of Dependency Injection.
[0] http://martinfowler.com/articles/injection.html
[1] http://www.codeplex.com/ObjectBuilder
[3] http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx