Introduction to Unity
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 Unity Application Block information can be found at the Unity Application Block site.|
The Unity Application Block (Unity) is a lightweight, extensible dependency injection container that supports constructor injection, property injection, and method call injection. It provides developers with the following advantages:
- It provides simplified object creation, especially for hierarchical object structures and dependencies, which simplifies application code.
- It supports abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns.
- It increases flexibility by deferring component configuration to the container.
- It has a service location capability; this allows clients to store or cache the container. This is especially useful in ASP.NET Web applications where developers can persist the container in the ASP.NET session or application.
This topic includes a series of brief sections that provide information to help you decide whether the Unity Application Block is suitable for your requirements. This topic includes the following sections:
- Common Scenarios
- Example Application Code
- Highlights of the Unity Application Block
- Determining When to Use the Unity Application Block
- Changes in This Release
In addition to this introductory material, the documentation contains the following topics:
- Developing Applications Using the Unity Application Block. This topic explains how to use the Unity Application Block in your applications. It lists the system requirements, explains how to configure the application block to perform common tasks, and shows how to add application code to the application block where required. It also lists the properties of the application block.
- Key Scenarios. This topic demonstrates how to use the application block to perform the most common operations.
- Design of the Unity Application Block. This topic explains the decisions that went into designing the application block and the rationale behind those decisions.
- Extending and Modifying the Unity Application Block. This topic explains how to extend the application block and how to modify the source code.
- Deployment and Operations. This topic explains how to deploy and update the application block's assemblies and use the instrumentation exposed by the application block.
- Unity QuickStarts. This topic walks through the QuickStart applications that demonstrate how to execute common operations in your applications.
For related information, see the following guidance:
- The Unity Community Web Site on CodePlex
- Loosen Up - Tame Your Software Dependencies for More Flexible Apps on MSDN
- Design Patterns: Dependency Injection in MSDN Magazine
- Unity Application Block 1.2 Class Library on MSDN
The Unity Application Block addresses the issues faced by developers engaged in component-based software engineering. Modern business applications consist of custom business objects and components that perform specific tasks or generic tasks within the application, in addition to components that individually address crosscutting concerns such as logging, authentication, authorization, caching, and exception handling.
The key to successfully building these types of applications is to achieve a decoupled or very loosely coupled design. Loosely coupled applications are more flexible and easier to maintain. They are also easier to test during development. You can mock up shims (lightweight mock implementations) of objects that have strong concrete dependencies, such as database connections, network connections, enterprise resource planning (ERP) connections, and rich user interface components.
Dependency injection is a prime technique for building loosely coupled applications. It provides ways to handle the dependencies between objects. For example, an object that processes customer information may depend on other objects that access the data store, validate the information, and check that the user is authorized to perform updates. Dependency injection techniques can ensure that the customer class correctly instantiates and populates all these objects, especially where the dependencies may be abstract.
The following design patterns define architectural and development approaches that simplify the process:
- Inversion of Control (IoC) pattern. This generic pattern describes techniques for supporting a plug-in architecture where objects can "look up" instances of other objects they require.
- Dependency Injection (DI) pattern. This is a special case of the IoC pattern and is an interface programming technique based on altering class behavior without the changing the class internals. Developers code against an interface for the class and use a container that injects dependent object instances into the class based on the interface or object type. The techniques for injecting object instances are interface injection, constructor injection, property (setter) injection, and method call injection.
- Interception pattern. This pattern introduces another level of indirection. This technique places an object between the client and the real object. A proxy is used between the client and the real object. The client behavior is the same as interacting directly to the real object, but the proxy intercepts them and solves their execution by collaborating with the real object and other objects as required.
This guidance includes the following scenarios to demonstrate the ways that you can use the Unity Application Block:
- Setting Up the Unity Container
- Resolving an Object by Type
- Resolving an Object by Type and Registration Name
- Resolving All Objects of a Particular Type
- Using BuildUp to Wire Up Objects Not Created by the Container
- Annotating Objects for Constructor Injection
- Annotating Objects for Property (Setter) Injection
- Annotating Objects for Method Call Injection
In addition, the Unity QuickStarts demonstrate many of these techniques, including a simple implementation of the Model-View-Presenter pattern and an implementation of an Event Broker service as a custom container extension.
By using dependency injection frameworks and inversion of control mechanisms, developers can generate and assemble instances of custom classes and objects that can contain dependent object instances and settings. The Unity Application Block supports this functionality, which enables developers to use techniques such as container-configured injection, constructor injection, property injection, and method call injection to generate and assemble instances of objects complete with all dependent objects and settings.
The Unity Application Block exposes two methods for registering types and mappings with the container:
- RegisterType. This method registers a type with the container. At the appropriate time, the container builds an instance of the type you specify. This could be in response to dependency injection initiated through class attributes or when you call the Resolve method. The lifetime of the object it builds corresponds to the lifetime you specify in the parameters of the method. If you do not specify a value for the lifetime, the type is registered for a transient lifetime, which means that the container creates a new instance on each call to Resolve.
- RegisterInstance. This method registers with the container an existing instance of a type that you specify, with the lifetime that you specify. The container returns the existing instance during that lifetime. If you do not specify a value for the lifetime, the instance has a container-controlled lifetime.
Container-Configured Registration of Types
As an example of using the overloads of the RegisterType and Resolve methods, the following code registers a mapping for an interface named IMyService and specifies that the container should return an instance of the CustomerService class (which implements the IMyService interface).
'Usage Dim myContainer As IUnityContainer = New UnityContainer() myContainer.RegisterType(Of IMyService, CustomerService)() Dim myServiceInstance As IMyService = myContainer.Resolve(Of IMyService)()
Container-Configured Registration of Existing Object Instances
As an example of using the overloads of the RegisterInstance and Resolve methods, the following code registers an existing instance of a class named LoggingService that implements the interface IMyService and then retrieves that instance.
'Usage Dim myContainer As IUnityContainer = New UnityContainer() Dim myExistingObject As New LoggingService() myContainer.RegisterInstance(Of IMyService)(myExistingObject) Dim myServiceInstance As IMyService = myContainer.Resolve(Of IMyService)()
As an example of constructor injection, if a class that developers instantiate using the Resolve method of the Unity container has a constructor that defines one or more dependencies on other classes, the Unity container automatically creates the dependent object instance specified in parameters of the constructor. For example, the following code shows a class named CustomerService that has a dependency on a class named LoggingService.
'Usage Public Class CustomerService Public Sub New(myServiceInstance As LoggingService) ' work with the dependent instance myServiceInstance.WriteToLog("SomeValue") End Sub End Class
At run time, developers create an instance of the CustomerService class using the Resolve method of the container, which causes the instance generation framework to inject an instance of the concrete class LoggingService within the scope of the CustomerService class.
'Usage Dim uContainer As IUnityContainer = New UnityContainer() Dim myInstance As CustomerService = uContainer.Resolve(Of CustomerService)()
Property (Setter) Injection
In addition to constructor injection, described earlier, the Unity Application Block supports property and method call injection. The following code demonstrates property injection. A class named ProductService exposes as a property a reference to an instance of another class named SupplierData (not defined in the following code). To force dependency injection of the dependent object, developers must apply the Dependency attribute to the property declaration, as shown in the following code.
'Usage Public Class ProductService Private supplier As SupplierData <Dependency()> _ Public Property SupplierDetails() As SupplierData Get Return supplier End Get Set (ByVal value As SupplierData) supplier = value End Set End Property End Class
Now, creating an instance of the ProductService class using the Unity Application Block automatically generates an instance of the SupplierData class and sets it as the value of the SupplierDetails property of the ProductService class.
|For more information about how you can use these and other features of the Unity Application Block in your applications, see Key Scenarios.|
The Unity Application Block includes the following features:
- It provides a mechanism for building (or assembling) instances of objects, which may contain other dependent object instances.
- It exposes RegisterType methods that support configuring the container with type mappings and objects (including singleton instances) and Resolve methods that return instances of built objects that can contain any dependent objects.
- It provides inversion of control (IoC) functionality by allowing injection of preconfigured objects into classes built by the application block. You can specify an interface or class type in the constructor (constructor injection), or you can apply attributes to properties and methods to initiate property injection and method call injection.
- It supports a hierarchy for containers. A container may have child container(s), which enables object location queries to pass from the child out through the parent container(s).
- It can read configuration information from standard configuration systems, such as XML files, and use it to configure the container.
- It makes no demands on the object class definition. There is no requirement to apply attributes to classes (except when using property or method call injection), and there are no limitations on the class declaration.
- It supports custom container extensions that you can implement; for example, you can implement methods to allow additional object construction and container features, such as caching.
Dependency injection provides opportunities to simplify code, abstract dependencies between objects, and automatically generate dependent object instances. However, the process may have a minor impact on performance, and it can increase complexity where only simple dependencies exist.
In general, you should use the Unity Application Block in the following situations:
- Your objects and classes may have dependencies on other objects or classes.
- Your dependencies are complex or require abstraction.
- You want to take advantage of constructor, method, or property call injection features.
- You want to manage the lifetime of object instances.
- You want to be able to configure and change dependencies at run time.
- You want to be able to cache or persist the dependencies across postbacks in a Web application.
You should not use the Unity Application Block in the following situations:
- Your objects and classes have no dependencies on other objects or classes.
- Your dependencies are very simple and do not require abstraction.
This release of Unity contains several minor changes to the source code. The following changes are included in this version of Unity:
- Fixed: Issues with building generic decorator chains are fixed.
- Fixed: The case that a null reference exception was thrown when looking at the message property of a cross-domain BuildFailedException is fixed. BuildFailedException and ResolutionFailedException now correctly serialize cross-domain. The BuildFailedException now retrieves the serialized fields in its serialization constructor.
- Added: Support was added for generic parameter injection configuration with the GenericParameter support in the InjectedMembers API. A new configuration element enables you to do the same configuration through a configuration file. Parameters and properties can now take a genericParameterName attribute. When genericParameterName is specified, only an optional dependency injection value can be set, and it cannot specify a type. Setting the genericParameterName causes a GenericParameter to be created; it uses the value set for genericParameterName and, optionally, the dependency element's name as the resolutionKey if such a dependency element exists and has a name.
- Added: A PerThreadLifetimeManager was added. The container returns the same instance on the same thread and a different instance on different threads.
- Fixed: Injection configuration for properties and methods is fixed. Now both default to DependencyElement.
- Changed: Registered names are now available as an ObjectBuilder policy so that you can actually do a ResolveAll from within the strategy chain. The container automatically registers itself with itself.
- Added: The implementation for the ResolvedArrayParameter support was added; it relies on the ResolveAll method in IUnityContainer. Both the core mechanism and the API support are implemented. Configuration support for ResolvedArray is provided with the <array> configuration element.
- Added: The new parameters, genericResolvedArray and a ParameterValue, GenericParameter, were added to the Unity configuration API for generic array support. Support for closed generics (public class MyClass<string>) has previously existed. Support for open generics (public class MyClass<T>) is new.
- Changed: Standard typeConfig configuration no longer requires an explicit extension type in the .config file. The default extension type is used when one is not specified. The extension type is now optional.
- Changed: The overloads for RegisterType now get InjectionMembers in order to configure injection without the need to call ConfigureInjectionFor.
- Added:InterceptionExtension.PolicyDefinition APIs were added to provide a simplified way to wire together RuleDrivenPolicies to support interception. The general purpose API requires repeated calls to the InjectedMembers.ConfigureInjectionFor and RegisterType methods. The streamlined extension API reduces the overhead required to manage the various strings and cross links, thus making the process more obvious and convenient.
- Added: Unity interception support was added, including configuration support. You can now define interceptors and when they should be used. Interceptors are defined like lifetime managers: you can just specify a type and you will get an instance of that type. You can also specify a value and, optionally, a type converter to provide more information about how the interceptor should be built.
- Fixed: Type converters specified through configuration are now properly handled and do not cause issues in multi-threaded applications.