BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 1.1+

Dependency Injection

Dependency injection is a technique used in object-oriented programming languages. It promotes loose coupling of components by passing dependencies to an object, rather than having an object instantiate its own dependencies.

Example Interface Injection

Earlier in this article I described two classes that allowed the monthly payments for a loan to be calculated. The PaymentTerms class was dependent upon the PaymentCalculator class. The two types were tightly coupled because a PaymentCalculator instance was instantiated directly in the dependent class's code. We will now decouple the classes with interface injection.

The first task is to create an interface for monthly payment calculators. We will name this, "IPaymentCalculator".

public interface IPaymentCalculator
{
    decimal GetMonthlyPayment(decimal Price, decimal Deposit, int Years);
}

We can now modify the PaymentCalculator class's declaration so that it implements the IPaymentCalculator interface, as follows:

public class PaymentCalculator : IPaymentCalculator

The next step is to create the interface that handles the injection. Only one dependency is required for the PaymentTerms class, so the interface includes a method that accepts one parameter of the IPaymentCalculator type.

public interface IPaymentCalculatorInjecter
{
    void InjectCalculator(IPaymentCalculator calculator);
}

Finally, the PaymentTerms class must be updated so that it implements the injection interface. In the code below the IPaymentCalculatorInjecter interface has been implemented with the injection method storing the dependency in a private field.

public class PaymentTerms : IPaymentCalculatorInjecter
{
    IPaymentCalculator _calculator;

    public void InjectCalculator(IPaymentCalculator calculator)
    {
        _calculator = calculator;
    }

    public decimal Price { get; set; }
    public decimal Deposit { get; set; }
    public int Years { get; set; }

    public decimal GetMonthlyPayment()
    {
        return _calculator.GetMonthlyPayment(Price, Deposit, Years);
    }
}

Testing the Interface Injection

We can test the interface injection example by executing the code below. This creates a new PaymentTerms object and injects a new PaymentCalculator object. The properties of the PaymentTerms object are then populated before outputting the monthly calculation to the console.

PaymentTerms pt = new PaymentTerms();
pt.InjectCalculator(new PaymentCalculator());
pt.Price = 10000;
pt.Years = 4;
pt.Deposit = 2500;
Console.WriteLine(pt.GetMonthlyPayment());  // Outputs "239.58"

Implementing Setter Injection

Setter injection allows the dependencies to be provided using writeable properties of a dependent class. This is similar to interface injection, in that a member is executed to inject a dependency. In some cases you will declare the properties in an interface. However, this is not necessary.

Setter Injection

The UML class diagram above describes an implementation of setter injection. The items in the diagram are described below:

  • Dependent. This class represents the dependent class. The dependency is injected using the "Dependency" property. In the UML, the dependency is stored in a private field.
  • IDependency. This interface describes the members provided by all dependencies that implement it.
  • Dependency. This class represents a dependency that may be injected into a dependent object.

The following shows the basic code for setter injection implemented using C#.

public interface IDependency
{
    void SomeMethod();
}


public class Dependency : IDependency
{
    public void SomeMethod()
    {
        Console.WriteLine("Dependency.SomeMethod() called");
    }
}


public class Dependent
{
    IDependency _dependency;

    public IDependency Dependency
    {
        set { _dependency = value; }
    }

    public void CallDependency()
    {
        _dependency.SomeMethod();
    }
}
12 September 2010