1

I understand that the dependency injection is something done by coding and its all done at compile time. And that Dependency injection coding is easily done now by helper tools like Ninject.

However this is at compile time that the dependency injection occurs. Then what does it mean that dependency injection also occurs at Runtime?

This is straight from wiki about Dependency Injection

Dependency injection is a software design pattern that allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time.

I mean I thought about it and came up with the idea that it may refer to multiple interfaces to a single class when a Delegate calls a metho from one of the interfaces, dependency injection decides something like this at runtime, but when I went deeper into it and even discussed it with my boss it sounded like its not that simple as that. And that then, how does the dependency injection makes this decision and assume it the correct one?

Anyone can help me clear out this question?

5 Answers 5

11

However this is at compile time that the dependency injection occurs.

The service type is defined at compile time. This is normally in the form of an interface or a (sometimes abstract) base class. The key point here is Liskovs substitution principle

It states that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may be substituted for objects of type T) without altering any of the desirable properties of that program (correctness, task performed, etc.)

So we know the contract of the type at compile time

Then what does it mean that dependency injection also occurs at Runtime?

When implementing DI, for example, using an Inversion of Control container the implementation type is not known until run time.

Let's look at a basic example of making a cup of coffee using Simple Injector as the Inversion of Control container and NUnit to test the code.

Firstly we define the cup and our service type:

public class Cup 
{
    public List<string> ingredients = new List<string>();
}

public interface ICoffeeService
{
    Cup GetCoffee();
}

And an implementation of the service:

public class CoffeeService : ICoffeeService
{
    public Cup GetCoffee()
    {
        Cup cup = new Cup();
        cup.ingredients.Add("Coffee powder");
        cup.ingredients.Add("Hot water");
        return cup;
    }
}

Our test method configures the container to return the CoffeeService when asked for an instance of ICoffeeService

[Test]
public void CoffeeService_GetCoffee_ReturnsCupWithCoffeeAndHotWater()
{
    // Arrange
    var container = new SimpleInjector.Container();
    container.Register<ICoffeeService, CoffeeService>();

    // Act
    var coffeeService = container.GetInstance<ICoffeeService>();
    var cup = coffeeService.GetCoffee();

    // Assert
    Assert.That(cup.ingredients.Count == 2);
    Assert.That(cup.ingredients.Contains("Coffee powder"));
    Assert.That(cup.ingredients.Contains("Hot water"));
}

We decide we need to always add cream to our coffee but instead of changing CoffeeService we instead Decorate it with the new feature (Open/Closed principle).

The decorator

public class AddCreamDecorator : ICoffeeService
{
    private readonly ICoffeeService decorated;

    public AddCreamDecorator(ICoffeeService decorated)
    {
        this.decorated = decorated;
    }

    public Cup GetCoffee()
    {
        Cup cup = this.decorated.GetCoffee();
        cup.ingredients.Add("Cream");
        return cup;
    }
}

And the new test

[Test]
public void DecoratedCoffeeService_GetCoffee_CupWithCoffeeAndHotWaterAndCream()
{
    // Arrange
    var container = new SimpleInjector.Container();
    container.Register<ICoffeeService, CoffeeService>();
    container.RegisterDecorator(typeof(ICoffeeService), typeof(AddCreamDecorator));

    // Act
    var coffeeService = container.GetInstance<ICoffeeService>();
    var cup = coffeeService.GetCoffee();

    // Assert
    Assert.That(cup.ingredients.Count == 3);
    Assert.That(cup.ingredients.Contains("Coffee powder"));
    Assert.That(cup.ingredients.Contains("Hot water"));
    Assert.That(cup.ingredients.Contains("Cream"));
}

The most important point to take from this example is that we code to and compile against the service type ICoffeeService and the container gives us the configured runtime implementation. In test one we get an instance of CoffeeService while in test two we get an instance of CoffeeService that is decorated with an instance of AddCreamDecorator - in both cases the caller doesn't care as it get the service it needs.

2
  • So in the second test case if we need an implementation of ICoffeeService without the decorator, how do we get that?
    – aamadmi
    Nov 8, 2014 at 7:28
  • One option with Simple Injector is to use runtime decorators
    – qujck
    Nov 8, 2014 at 10:14
5

Dependency injection simply means that you pass in one or more interface implementations, typically to the constructor of the class. The class methods then in turn call methods on these interfaces rather than calling out e.g. to a library directly.

When you do this you can defer the decision about exactly what implementation you want to pass in (inject) until run-time where the decision as to which particular implementation should be used might for instance get configured through a configuration file.

3
  • yes, change the configuration and change the runtime behavior. basically Dependency injection to me means: writing java changed to writing XML
    – zinking
    Nov 20, 2013 at 1:35
  • I would rather say that dependency injection means that you declare one or more interface implementations that need to be passed in". The entire point of DI is that you generally don't pass parameters to the constructor directly; instead you declare parameters that need to be injected, and the framework does the heavy-lifting of finding the right type, instantiating it, and passing it as that parameter for you.
    – Kirk Woll
    Nov 20, 2013 at 2:57
  • 3
    @KirkWoll: You can reap many benefits of DI without going with a full-blown DI framework/container which brings its own dependency into the picture. A simple factory and/or builder pattern will do nicely. Nov 20, 2013 at 8:11
2

Your understanding of Dependency Injection is correct and when you do this by coding it will be done at compile time. To have dependencies injected at run time you need Dependency Injection Container (Provider). It basically does the coding for you, you just need to configure it so it can pass the right parameters.

1

I haven't used Ninject in a project myself, but I'm familiar with it, so I'll try to use it for an example.

A dependency that is changed at compile-time would be one that is explicitly configured in code which is run at startup of the program. e.g. for the Ninject docs:

Bind<IWeapon>().To<Sword>();

A dependency that is changed at run-time would be one that is configured to use a provider, rather than a concrete type, e.g.

Bind<IWeapon>().ToProvider(new SwordProvider());

Then, the SwordProvider class could provide a CreateInstance() implementation which, say, hits a database to determine which concrete class to supply. Hence, behaviour could be changed at runtime by updating the database. Or whatever.

1

I'm late to the party, but I noticed that no one else answered the actual question. Here's a simple example of runtime DI:

First you need an object with a dependency:

public MyRoom(ILightFixture fixture)
{
  this.MyLightFixture = fixture ; 
}

And then, in your composition root, include a run-time decision:

public void Main()
{
  // make runtime decision (e.g. input from user); respond dynamically...
  ...
  if (userChoice == "Classy")
     room = new MyRoom(new ClassyChandelier());
  else
     room = new MyRoom(new SubduedSconce());
}

Simple as that. Now the mood of your room object is determined dynamically (at runtime).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.