This project is read-only.

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.
ClassAHasDependenciesOnServiceAAndServiceB.png
Figure 1
The ClassA has dependencies on the ServiceA and the ServiceB.

This situation brings up the following problems:
  • To replace or update the dependencies, you need to change your classes’ source code.
  • The concrete implementation of the dependencies has to be available at compile time.
  • Your classes are difficult to test in isolation because they have a direct reference to the dependencies and therefore they cannot be replaced with stubs or mocks.

Forces

  • You want to decouple your classes from its dependencies so the dependencies can be replaced or updated requiring minimal or no changes to your classes’ source code.
  • You want to be able to write classes that depend on services whose concrete implementation is not known at compile time.
  • You want to be able to test your classes in isolation (without using the service dependencies).

Solution

Do not instantiate the dependencies explicitly in your class. Instead, express dependencies declaratively in your class definition and use a separate object to obtain valid instances of your object’s dependencies and pass them to your object during the object 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, the object being built gets the dependencies through parameters of the object’s constructor method. In setter injection, the object exposes a setter property which is used to pass the dependencies to it during object initialization.

Implementation with ObjectBuilder and the Composite Web Application Block

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 using the [ServiceDependency] attribute. This attribute indicates to ObjectBuilder that it has to 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 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 enable 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.
  • There is added complexity to the source code; therefore, it is harder to understand.

More Information

  • To better understand how ObjectBuilder enables you to use the Dependency Injection pattern, see ObjectBuilder.

Related Patterns

  • Service Locator. The Service Locator pattern solves the same problems that the Dependency Injection pattern solves, but it uses a different approach.

Last edited Nov 20, 2007 at 12:42 PM by ejadib, version 2

Comments

No comments yet.