Unity is an open-source project from the Patterns & Practices group at Microsoft aimed at providing a classic IoC framework for developers to build object instances in a smart and highly configurable way. Unity works as a standalone framework but it is often packaged along with Enterprise Library. With the advent of .NET 4 and Visual Studio 2010 new releases of both Unity and Enterprise Library are in order. This article takes a look at the beta of Unity 2.0. To get the bits and try it out yourself, pay a visit to http://unity.codeplex.com. Unity 2.0 and Enterprise Library 5.0 are slated for release in the same timeframe as Visual Studio 2010 and .NET 4 this spring.
Quick Facts about Unity 2.0
When a new release of a development product ships, the first question is: can I just replace old binaries with new binaries and be happy? A second question is often: can I use old and new binaries side by side? For Unity 2.0 the answer is yes for both questions. You can simply migrate existing applications to the new version of the tool and you can also have version 1.2 and 2.0 of Unity run side by side in the context of the same application. However, in case of a side by side choice you need to maneuver a bit and ensure, for example, that Unity assemblies go in different directories (they still have the same name) and each assembly depends on just one version of Unity.
Speaking of assemblies, it should be noted that all the functionalities of Unity 2.0 span over three assemblies, as listed below.
The first contains the core of the library, whereas the other two focus on specific aspects such as support for XML offline configuration and interception. A remarkable difference with previous versions is that lack of the ObjectBuilder2 assembly whose code has now been incorporated in the core assembly.
Depending on how you used Unity 1.2 and the features you employed, you may or may not encounter troubles migrating your existing code to the new version. At first sight, my impression is that in most cases it will work seamlessly, but some changes exist and some of the old code may appear as deprecated in light of the new version.
Expressing Dependencies with Unity 2.0
Because the main purpose of Unity is resolving dependencies that classes have on other classes, the first task to approach is how those dependencies can be expressed. This can be done in two ways - using an offline configuration file or via a fluent API at run time.
By default, Unity reads configuration parameters from an XML file, typically the application's configuration file whether app.config or web.config. You are not limited to that, however. You can load configuration parameters from any XML file that has been mapped to the executable. Suppose you have a my.config file properly set up with Unity information. The following code snippet shows you how to load that information into the current instance of the container.
This code is slightly different from what you would have used in version 1.2. The older code is now declared obsolete. The big difference is in the line that loads configuration information into the container. Now you have a new Configure method on the section object.
Note that if you use a non-default configuration file, then you must ensure that the .config file is deployed in the output directory of the executable. Here's instead the code you need if you go with the default configuration file:
The resulting code is certainly clearer than in the past. However, there's an even better news for Unity developers: a very nice configuration tool through which you can "express and declare" your dependencies. The tool is the same you would use for Enterprise Library 5.0. Have a look at Figure 1.
Figure 1: The Unity section edited through the Enterprise Library configuration tool.
The tool can save to any file you choose and can combine together multiple sections from both Enterprise Library blocks and Unity. The tool also can open files you create manually in Visual Studio or otherwise.
The offline configuration is an excellent thing but it is still a declarative API. There are situations in which you need more flexibility and, of course, situations in which you just prefer using an approach that provides for more flexibility. The alternative to design-time, offline configuration is run time configuration.
The UnityContainer class supports a fluent syntax that allows you to chain any combination of the methods of the class to reach the desired configuration. As an example, you can use
RegisterType to register a type mapping and
RegisterInstance to register an instance for a particular type. You can also combine in the same call
AddExtension to deal with the interception API of Unity. The UnityContainer class also features a new
IsRegistered extension method for you to check whether a given type is already registered with the framework.
The method is one of the new features added to Unity 2.0 and is useful in a scenario where you intend to integrate design time and run time configuration. You can use the method to avoid multiple identical registrations which would be automatically resolved according to the last-win policy. In fact, when a type is registered more than once, and the registrations are not disambiguated using a name, only the last entered will be taken into account by the resolver component. In Unity 2.0, you also find a new Registrations collection to inspect programmatically the registrations available at some point. The Registrations member returns a collection of ContainerRegistration objects, defined as below.
As you can see, a ContainerRegistration object represents a faithful description of a registration whether you made it via XML or programmatically.
Resolving Dependencies with Unity 2.0
Unity 2.0 still provides a resolver method with the same syntax you may know from previous versions. Once the container has been configured in some way, all that remains to do is building instances of mapped types. This is the purpose of the
The resolver method does the magic of exploring the structure of the target type and finds out whether it has dependencies to be resolved. Like many other IoC frameworks, Unity supports dependencies specified through the constructor and injection attributes that can be specified for properties and method calls. The instance returned by
Resolve<T> has all dependencies solved otherwise an exception is thrown by the framework.
Unity can resolve generic types too whether they are bound or unbound. Here's a sample registration that involves an unbound generic type (where type T is not known):
The ISpecialLogger<T> type is mapped to a closed type that just knows how to handle integers. Here's a sample definition for the type.
In code, you ask Unity to resolve ISpecialLogger<int> and get an object that knows how to log an integer.
Circular references are a serious danger with Unity and with IoC frameworks in general. Circular dependencies are not easy to catch for a tool and should be considered a sign of bad design, rather than the unfortunate result of a feature that your IoC lacks. When a class supplies multiple constructors, Unity defaults to the one with highest number of parameters. This may actually create the occurrence of a circular reference that you would never incur as long as you handle instantiation of classes manually. Consider the following two classes:
All is good if you take control of the instantiation yourself and use the following code:
If you delegate Unity to resolve the class you get a stack overflow:
The reason of the stack overflow exception is that Unity ends up using the longest constructor thus incurring in a circular reference when it attempts to get an instance of MyService to resolve MyContainer whereas an instance of MyContainer is needed to instantiate MyService.
Finally, it should be noted that Unity 2.0 adds a couple of new lifetime managers. In the previous version, we had three predefined lifetime managers, plus the ability to create our own ones. Table 1 supplies the list of managers in Unity 2.0.
Table 1: Lifetime managers in Unity 2.0
Implements a singleton behavior for objects. The object is disposed of when you dispose of the container.
Implements a singleton behavior but the container doesn't hold a reference to object which will be disposed of when out of scope.
New in Unity 2.0, implements a singleton behavior for objects. However, child containers don't share instances with parents.
New in Unity 2.0, implements a behavior similar to the transient lifetime manager except that instances are reused across build-ups of the object graph.
Implements a singleton behavior for objects but limited to the current thread.
Returns a new instance of the requested type for each call. This is the default behavior.
As expected, the default behavior of the Unity resolver is returning a brand new instance per each call. This is the same as in previous versions.
At the time of this writing, Unity 2.0 is still in Beta but feature complete. It doesn't come as a brand new and revolutionary release. However, it fixes configuration - an area where it was clearly insufficient, at least if compared to other blocks in the companion Enterprise Library - both from an API and designer perspective. And if you use just plain dependency injection you only need a single DLL.
The final release is expected to ship in April shortly following the release of Visual Studio 2010 and the .NET Framework 4. However, Unity is not specific of .NET 4 and works also for .NET 3.5
Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...
This author has published 54 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.