When Should I Use Unity?
Dependency injection provides opportunities to simplify code, abstract dependencies between objects, and automatically generate dependent object instances. In general, you should use Unity when:
- You wish to build your application according to sound object oriented principles (following the five principles of class design, or SOLID), but doing so would result in large amounts of difficult-to-maintain code to connect objects together.
- 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 intercept calls to methods or properties to generate a policy chain or pipeline containing handlers that implement crosscutting tasks.
- You want to be able to cache or persist the dependencies across post backs in a Web application.
The following sections provide more information to help you decide whether Unity is suitable for your requirements:
|Enterprise Library, also from the Microsoft patterns & practices group, uses Unity as its primary mechanism for generating instances of Enterprise Library objects. For information about this and other features of Enterprise Library, see the Enterprise Library Community site on CodePlex, or the Microsoft Enterprise Library pages on MSDN®.|
Unity 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 a proxy object between the client and the real object. The client behavior is the same as when interacting directly to the real object, but the proxy intercepts the calls and manages their execution by collaborating with the real object and other objects as required.
Unity provides developers with the following advantages:
- It provides simplified object creation, especially for hierarchical object structures and dependencies, which simplifies application code. It contains a mechanism for building (or assembling) instances of objects, which may contain other dependent object instances.
- It supports abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify the management of crosscutting concerns.
- It increases flexibility by deferring component configuration to the container. It also supports a hierarchy for containers.
- It has a service location capability, which is useful in many scenarios where an application makes repeated use of components that decouple and centralize functionality.
- It 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.
- It has an interception capability, which allows developers to add functionality to existing components by creating and using handlers that are executed before a method or property call reaches the target component, and again as the calls returns.
- 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.
- It allows architects and developers to more easily implement common design patterns often found in modern applications.
Dependency injection through Unity can have a minor impact on performance, and it can increase complexity where only simple dependencies exist. You should not use Unity in the following situations:
- When your objects and classes have no dependencies on other objects or classes.
- When your dependencies are very simple and do not require abstraction.