Dependency Injection: Factory vs Container – Unity
As application size and complexity increase it becomes more and more difficult to reuse existing components and integrating these components to form an interconnected architecture because of the dependencies of the components. One way to reduce dependencies is by using Dependency Injection, which allows you to inject objects into a class, rather than relying on the class to create the object itself.
Dependency Injection refers to the process of supplying an external dependency to a software component. It is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency. The basic value Dependency Injection brings to enterprise systems is decoupling. They promote programming to interfaces and isolate you from the creation process of the collaborators, letting you to concentrate on what you need to deliver while improving testing.
The dependency injection approach offers more flexibility because it becomes easier to create alternative implementations of a given service type, and then to specify which implementation is to be used either pragmatically or via a configuration file, without any change to the objects that use the service. This is especially useful in unit testing, because it is easy to inject a mock implementation of a service into the object being tested.
Dependency injection helps in solving the following
The factory pattern described as "To construct and instantiate a set of related objects without specifying their concrete objects." is one common way to implement Dependency Injection. When a component creates an instance of another class, it encapsulates the object creation logic within the component. Any other class that requires an instance of the created class must also duplicate the object creation logic as it may not be reusable outside the component.
Object most often need to be instantiated in a coordinated fashion, usually because of certain dependencies or other requirements. For example, when creating an instance of XmlValidatingReader in client code, an XmlSchemaCollection object is frequently populated with the relevant schemas for use when validating the XmlValidatingReader object. This is an example of needing to not only create an instance of a class, but also to configure it after creation and before it can be used.
Another example of a factory pattern is to create a static method whose purpose is to return an instance of a class. For example, the Create method of WebRequest takes in either a string or Uri instance, and returns a new instance of a class derived from WebRequest.
Factories allow for an application to wire together objects and components without exposing too much information about how the components fit together or what dependencies each component might have. Instead of spreading complex creating code around an application, factories allow for that code to be housed in a central location, thereby facilitating reuse throughout the application.
Client code then calls creating methods on the factory, with the factory returning complete instances of the requested classes. Encapsulation is preserved, and the client is effectively decoupled from any sort of plumbing required to create or configure the object instance.
Benefits of Factory Pattern
Drawbacks of factory pattern
A container is a compartment that houses some sort of abstraction within its walls. Typically, responsibility for object management is taken over by whatever container is being used to manage those objects. However, containers can also take over instantiations, configuration, as well as the application of container-specific services to objects.
Containers provide the ability to wrap vanilla objects with a wealth of other services. This allows the objects to remain ignorant about certain infrastructure and plumbing details, like transactionality and role-based security. Oftentimes, the client code does not need to be aware of the container, so there is no real dependency on the container itself. Containers be configured declaratively, meaning they can be configured via some external means, XML files, property files, or .NET-based attributes.
Dependency Injection is a worthwhile concept to explore for use within applications that you develop. Not only can it reduce coupling between components, but it also saves you from writing boilerplate factory creation code over and over again. Unity is an example of a framework that provides a ready to use Dependency Injection container. Of course all this also means that there is added complexity to the source code; therefore, it is harder to understand.
Microsoft Patterns and Practices team had been developing Enterprise Library to enable the use of general patterns and practices for .NET platform, which has great pluggable application blocks such as Logging and Validation application blocks. One of them is the Dependency Injection Application Block; but folks thought it should be named differently from the other application blocks, and came with the fancy name Unity.
Unity exposes Register methods that support configuring the container with mappings and objects (including singleton instances), and Resolve methods to return instances of built objects that contain any dependent objects. Unity sits on top of another framework called ObjectBuilder which has been a part of enterprise library for quite some time. Unity however is based on v2.0 of the object builder which has been tweaked, refactored and optimized for performance. Unity is available as both a standalone download or part of the enterprise library and can be downloaded from http://www.codeplex.com/unity or http://www.codeplex.com/entlib.
Unity supports the following forms of dependency injection:
David Hayden has done some great screencasts on Enterprise Library and Unity at http://www.pnpguidance.net/ be sure the check them out for furhter readings on dependency injection using Unity Applicaiton Block.