Introduction to Unity
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. |
The Unity Application Block (Unity) is a lightweight, extensible dependency injection container with support for constructor, property, 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 the 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.
More Information
For related information, see the following guidance:
- The Unity Community Web Site on CodePlex
- Loosen Up - Tame Your Software Dependencies for More Flexible Apps
- Design Patterns: Dependency Injection in MSDN Magazine
Common Scenarios
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 or generic tasks within the application, in addition to components that individually address cross cutting concerns such as logging, authentication, authorization, caching, and exception handling.
The key to successfully building such 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, 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:
- The 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.
- The 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.
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.
Example Application Code
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, allowing 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 will build 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 will correspond 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 will create 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 will return the exiting instance during that lifetime. If you do not specify a value for the lifetime, the instance will have 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).
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IMyService, CustomerService>();
IMyService myServiceInstance = myContainer.Resolve<IMyService>();
'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.
IUnityContainer myContainer = new UnityContainer();
LoggingService myExistingObject = new LoggingService();
myContainer.RegisterInstance<IMyService>(myExistingObject);
IMyService myServiceInstance = myContainer.Resolve<IMyService>();
'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)()
Constructor Injection
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 will automatically create 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.
public class CustomerService
{
public CustomerService(LoggingService myServiceInstance)
{
// work with the dependent instance
myServiceInstance.WriteToLog("SomeValue");
}
}
'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.
IUnityContainer uContainer = new UnityContainer();
CustomerService myInstance = uContainer.Resolve<CustomerService>();
'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.
public class ProductService
{
private SupplierData supplier;
[Dependency]
public SupplierData SupplierDetails
{
get { return supplier; }
set { supplier = value; }
}
}
'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 will automatically generate an instance of the SupplierData class and set it as the value of the **SupplierDetails **property of the ProductService class.
Note
For more details of how you can use these and other features of the Unity Application Block in your applications, see Key Scenarios.
Highlights of the Unity Application Block
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. Developers can specify an interface or class type in the constructor (constructor injection), or 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), allowing 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 developers can implement; for example, methods to allow additional object construction and container features such as caching.
Determining When to Use the Unity Application Block
Dependency injection provides opportunities to simplify code, abstract dependencies between objects, and generate dependent object instances automatically. 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.
Changes in This Release
This release of the Unity Application Block contains several minor changes to the source code. These changes include the following:
- Removal of all obsolete ObjectBuilder code
- Fix for a bug when using lifetime managers with open generic types
- Fix for a bug where the RegisterType method was overriding the RegisterInstance method
- Performance improvement when resolving singletons
- Exposure of some additional internal classes as public to make it easier write extensions that need to resolve dependencies in a customized way
- Addition of try...catch blocks to improve the error messages returned when value resolution fails
These changes do not affect the API of Unity, or the way that you use it.