Design of the Unity Application Block

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

The latest Enterprise Library information can be found at the Enterprise Library site.

This topic describes the design goals, the architecture, and the design highlights of the Unity Application Block. You do not have to understand the design to use Unity; however, this topic will help you to understand how it works and how it interacts with the underlying ObjectBuilder subsystem. This topic contains the following sections:

  • Design Goals
  • Design Highlights

Design Goals

The Unity Application Block was designed to achieve the following goals:

  • Promote the principles of modular design through aggressive decoupling.
  • Raise awareness of the need to maximize testability when designing applications.
  • Provide a fast and lightweight dependency injection container mechanism for creating new object instances and managing existing object instances.
  • Expose a compact and intuitive API for developers to work with the container.
  • Support a wide range of code languages, with method overrides that accept generic parameters where the language supports these.
  • Implement attribute-driven injection for constructors, property setters, and methods of target objects.
  • Provide extensibility through custom and third-party container extensions.
  • Provide the performance required in enterprise-level Line of Business (LOB) applications.

Design Highlights

Figure 1 illustrates the main components of the Unity Application Block and the initialization sequence that prepares Unity to perform dependency injection.

Ff650476.c9543472-5a59-4e21-a55e-156ab9a4994d(en-us,PandP.10).png

Figure 1
The architecture and initialization of the main classes in the Unity Application Block

Note

The UnityContainer class also exposes the Teardown method, which notionally would reverse the build-up process. However, the base implementation of this method does nothing. The implementation exists so that container extensions can execute their own custom overrides of this method if required.

Initialization

When code initializes a UnityContainer instance, the constructor creates within its context instances of the classes required to prepare ObjectBuilder and pass information to it so that it can perform the appropriate object generation process. These classes are defined by ObjectBuilder and include the following:

  • The NamedTypesRegistry class, which stores a list of registered types
  • A generic List that holds references to UnityContainerExtension instances added to the container
  • The Locator class, which locates existing instances of registered types
  • The LifetimeContainer class, which manages the lifetime of registered objects and disposes of them when the container is disposed
  • Two instances of the StagedStrategyChain, which store the build strategies and build plans for ObjectBuilder to use when creating instances of registered types
  • The PolicyList class, which contains the policies ObjectBuilder will use when examining objects and classes during the build process

During the next stage of initialization, the UnityContainer adds two container extensions named UnityDefaultStrategiesExtension and UnityDefaultBehaviorExtension that implement and manage the Unity processes.

The UnityDefaultStrategiesExtension adds to the container context the two StagedStrategyChain instances created during initialization that specify the main strategy chain and the build plan strategy chain. These strategy chains determine how ObjectBuilder will handle constructor injection, property injection, and method call injection. The UnityDefaultStrategiesExtension also adds three ObjectBuilder policies to the current container context that specify the three attributes (the InjectionConstructor, Dependency, and InjectionMethod attributes) that ObjectBuilder will look for when reflecting over the object it creates.

The UnityDefaultBehaviorExtension registers event handlers for the type registration events that Unity supports:

  • Registering. This registers the type name in the container context and adds a BuildKeyMappingPolicy to the context that specifies how ObjectBuilder will resolve type mappings. It also adds any specified lifetime manager to the context lifetime policies.
  • RegisteringInstance. This registers the instance in the container context and adds any specified lifetime manager to the context lifetime policies.

Operation

The public methods of the UnityContainer that developers use fall into two main categories:

  • Methods that register mappings or types. These methods raise the Registering or the RegisteringInstance event. This causes the UnityDefaultBehaviorExtension to create the appropriate policies and locator entries within the current container context.
  • Methods that retrieve objects. These include overrides of the Resolve, ResolveAll, and BuildUp methods. All these methods eventually call a private method of the UnityContainer class named DoBuildUp. This method retrieves the required instances of the objects that ObjectBuilder requires to perform the object creation process. These objects include the NamedTypesRegistry, Locator, LifetimeContainer, the list of container extensions, and the strategies and policies created during initialization and through registration of type mappings, singletons, and object instances. The DoBuildUp method then executes the BuildUp method in ObjectBuilder and returns the resulting object.