This project is read-only.
Inversion of Control | Service Locator

Dependency Injection

Problem

You have classes that have dependencies on services or components whose concrete type is specified at design time. In this example, ClassA has dependencies on ServiceA and ServiceB.
Dependencies.png
Figure 1
ClassA has dependencies on ServiceA and ServiceB

This situation has the following problems:
  • To replace or update the dependencies, you need to change your classes’ source code.
  • The concrete implementations of the dependencies have to be available at compile time.
  • Your classes are difficult to test in isolation because they have a direct reference to the dependencies. This means that these dependencies cannot be replaced with stubs or mocks.
  • Your classes contain repetitive code for creating, locating, and managing their dependencies.

Forces

  • You want to decouple your classes from their dependencies so that the dependencies can be replaced or updated with minimal or no changes to your classes’ source code.
  • You want to write classes that depend on services whose concrete implementation is not known at compile time.
  • You want to test your classes in isolation, without using the service dependencies.
  • You want to decouple your classes from being responsible for locating and managing the lifetime of dependencies.

Solution

Do not explicitly instantiate the dependencies in your class. Instead, use the Dependency Injection pattern and declaratively express the dependencies in your class definitions and use a separate object, which in this example is named a Builder, to obtain valid instances of your object’s dependencies. Use the Builder to pass the dependencies to your object during the object’s creation and/or initialization. This is illustrated in Figure 2.
ConceptualView-DependencyInjectionPattern.PNG
Figure 2
Conceptual view of the Dependency Injection pattern

The two main forms of dependency injection are:
  • Constructor injection
  • Setter injection
In constructor injection, you use parameters of the object’s constructor method to inject it with its dependencies. In setter injection, the object exposes setter properties that the builder uses to pass the dependencies to it during object initialization.

Implementation of Dependency Injection with ObjectBuilder

ObjectBuilder is an open source framework for creating dependency injection systems, largely used in the Composite Web Application Block and in related projects such as the Composite UI Application Block and Enterprise Library.
ObjectBuilder uses a locator to store references to components and services. In your class source code, you declaratively express dependencies with the [ServiceDependency] attribute. This attribute indicates to ObjectBuilder that it must search for a valid instance of the dependency in the locator and inject it when building an object of the type of your class.
The following code demonstrates how to use the [ServiceDependency] attribute when implementing setter injection.

private IAccountServices  _accountServices;

[ServiceDependency]
public IAccountServices AccountServices
{
  set { _accountServices = value; }
} 

The [ServiceDependency] attribute can also be applied to parameters of a method. Therefore, you can implement constructor injection by adding the attribute to parameters of a constructor method.
The following code demonstrates how to use constructor injection.

public class ElectronicFundsTransferController
{
  private IAccountServices  _accountServices;

  public ElectronicFundsTransferController
    (
      [ServiceDependency] IAccountServices accountServices
    )
  {
    _accountServices = accountServices;
  }
  ...
} 

Liabilities

  • There are more solution elements to manage.
  • You have to ensure that, before initializing an object, the dependency injection framework can resolve the dependencies that are required by the object.
  • There is added complexity to the source code, which makes it harder to understand.

Related Patterns

  • Service Locator. The Service Locator pattern solves the same problems that the Dependency Injection pattern solves, but it uses a different approach.
  • Inversion of Control. The Dependency Injection pattern is a specialized version of the Inversion of Control pattern.
Inversion of Control | Service Locator

Last edited Jan 17, 2008 at 4:13 PM by siacomuzzi, version 3

Comments

No comments yet.