54

I have been looking at the terms constructor injection and dependency injection while going through articles on (Service locator) design patterns.

When I googled about constructor injection, I got unclear results, which prompted me to check in here.

What is constructor injection? Is this a specific type of dependency injection? A canonical example would be a great help.

Edit

Revisiting this questions after a gap of a week, I can see how lost I was... Just in case anyone else pops in here, I will update the question body with a little learning of mine. Please do feel free to comment/correct.

Constructor injection and property injection are two types of Dependency Injection.

1

3 Answers 3

108

I'm no expert, but I think I can help. And yes, it's a specific type of Dependency Injection.

Disclaimer: Almost all of this was "stolen" from the Ninject Wiki

Let’s examine the idea of dependency injection by walking through a simple example. Let’s say you’re writing the next blockbuster game, where noble warriors do battle for great glory. First, we’ll need a weapon suitable for arming our warriors.

class Sword 
{
    public void Hit(string target)
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}

Then, let’s create a class to represent our warriors themselves. In order to attack its foes, the warrior will need an Attack() method. When this method is called, it should use its Sword to strike its opponent.

class Samurai
{
    readonly Sword sword;
    public Samurai() 
    {
        this.sword = new Sword();
    }

    public void Attack(string target)
    {
        this.sword.Hit(target);
    }
}

Now, we can create our Samurai and do battle!

class Program
{
    public static void Main() 
    {
        var warrior = new Samurai();
        warrior.Attack("the evildoers");
    }
}

As you might imagine, this will print Chopped the evildoers clean in half to the console. This works just fine, but what if we wanted to arm our Samurai with another weapon? Since the Sword is created inside the Samurai class’s constructor, we have to modify the implementation of the class in order to make this change.

When a class is dependent on a concrete dependency, it is said to be tightly coupled to that class. In this example, the Samurai class is tightly coupled to the Sword class. When classes are tightly coupled, they cannot be interchanged without altering their implementation. In order to avoid tightly coupling classes, we can use interfaces to provide a level of indirection. Let’s create an interface to represent a weapon in our game.

interface IWeapon
{
    void Hit(string target);
}

Then, our Sword class can implement this interface:

class Sword : IWeapon
{
    public void Hit(string target) 
    {
        Console.WriteLine("Chopped {0} clean in half", target);
    }
}

And we can alter our Samurai class:

class Samurai
{
    readonly IWeapon weapon;
    public Samurai() 
    {
        this.weapon = new Sword();
    }
    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }
}

Now our Samurai can be armed with different weapons. But wait! The Sword is still created inside the constructor of Samurai. Since we still need to alter the implementation of Samurai in order to give our warrior another weapon, Samurai is still tightly coupled to Sword.

Fortunately, there is an easy solution. Rather than creating the Sword from within the constructor of Samurai, we can expose it as a parameter of the constructor instead. Also known as Constructor Injection.

class Samurai
{
    readonly IWeapon weapon;
    public Samurai(IWeapon weapon) 
    {
        this.weapon = weapon;
    }
    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }
}

As Giorgio pointed out, there's also property injection. That would be something like:

class Samurai
{
    IWeapon weapon;

    public Samurai() { }


    public void SetWeapon(IWeapon weapon)
    {
        this.weapon = weapon;
    }

    public void Attack(string target) 
    {
        this.weapon.Hit(target);
    }

}

Hope this helps.

6
  • 8
    Loved this one! :) It actually read like a story! Just curious. If you wanted to arm the same Samurai with multiple weapons (sequentially), property injection would be the best way right? Nov 29, 2012 at 12:51
  • Yes, you could do that. Actually, I think you would be better served passing the IWeapon as a parameter to the Attack method. Like "public void Attack(IWeapon with, string target)". And to avoid duplicate code I'd make the existing method "public void Attack(string target)" intact and make it call "this.Attack(this.weapon, target)". Nov 29, 2012 at 13:05
  • And then combined with factories, you can get methods such as CreateSwordSamurai()! Nice example.
    – Geerten
    Dec 10, 2012 at 14:18
  • 2
    Great example! So clear... Apr 25, 2015 at 20:19
  • @Luiz Angelo. Sorry, I'm not sure I understood your comment: "Actually, I think you would be better served passing the IWeapon as a parameter to the Attack method. Like..". You mean overload the Attack method in the Samurai class?
    – Pap
    Apr 12, 2017 at 10:29
4

I will try as much as possible to make this very elementary. That way, you can build on the concept and create your own complex solutions or ideas.

Now imagine we have a church called Jubilee, which has branches world wide. Our aim is to simply get an item from each branch. Here would be the solution with DI;

1) Create an interface IJubilee:

public interface IJubilee
{
    string GetItem(string userInput);
}

2) Create a class JubileeDI which would take the IJubilee interface as a constructor and return an item:

public class JubileeDI
{
    readonly IJubilee jubilee;

    public JubileeDI(IJubilee jubilee)
    {
        this.jubilee = jubilee;
    }

    public string GetItem(string userInput)
    {
        return this.jubilee.GetItem(userInput);
    }
}

3) Now create three braches of Jubilee namely JubileeGT, JubileeHOG, JubileeCOV, which all MUST inherit the IJubilee interface. For the fun of it, make one of them implement its method as virtual:

public class JubileeGT : IJubilee
{
    public virtual string GetItem(string userInput)
    {
        return string.Format("For JubileeGT, you entered {0}", userInput);
    }
}

public class JubileeHOG : IJubilee
{
    public string GetItem(string userInput)
    {
        return string.Format("For JubileeHOG, you entered {0}", userInput);
    }
}

public class JubileeCOV : IJubilee
{
    public string GetItem(string userInput)
    {
        return string.Format("For JubileCOV, you entered {0}", userInput);
    }
}

public class JubileeGTBranchA : JubileeGT
{
    public override string GetItem(string userInput)
    {
        return string.Format("For JubileeGT branch A, you entered {0}", userInput);
    }
}

4) That is it! Now let us see DI in action:

        JubileeDI jCOV = new JubileeDI(new JubileeCOV());
        JubileeDI jHOG = new JubileeDI(new JubileeHOG());
        JubileeDI jGT = new JubileeDI(new JubileeGT());
        JubileeDI jGTA = new JubileeDI(new JubileeGTBranchA());

        var item = jCOV.GetItem("Give me some money!");
        var item2 = jHOG.GetItem("Give me a check!");
        var item3 = jGT.GetItem("I need to be fed!!!");
        var item4 = jGTA.GetItem("Thank you!");

For each instance of the container class, we pass a new instance of the class we require, which enables loose coupling.

Hope this explains the concept in a nutshell.

2

Suppose that you have a class A each instance of which that needs an instance of another class B.

class A
{
   B b;
}

Dependency injection means that the reference to B is set by the object that manages the instance of A (as opposed to having the class A managing the reference to B directly).

Constructor injection means that the reference to B is passed as a parameter to the constructor of A and set in the constructor:

class A
{
    B b;

    A(B b)
    {
        this.b = b;
    }
}

An alternative is to use a setter method (or a property) to set the reference to B. In this case, the object that manages an instance a of A must first call the constructor of A and later call the setter method to set the member variable A.b before a is used. The latter injection method is necessary when objects contain cyclic references to each other, e.g. if an instance b of B that is set in an instance a of A contains a back reference to a.

** EDIT**

Here are some more details to address the comment.

1. Class A manages B instance

class A
{
    B b;

    A()
    {
        b = new B();
    }
 }

2. B instance is set in the constructor

class A
{
    B b;

    A(B b)
    {
        this.b = b;
    }
}

class M
{
    ...
    B b = new B();
    A a = new A(b);
}

3. B instance is set using setter method

class A
{
    B b;

    A()
    {
    }

    void setB(B b)
    {
        this.b = b;
    }
}

class M
{
    ...
    B b = new B();
    A a = new A();

    a.setB(b);
}
6
  • ...as opposed to having the class A managing the reference to B directly. What does this mean? How would you do it in code? (Pardon my ignorance.) Nov 29, 2012 at 11:13
  • 2
    The samurai example is so much better. Let's all stop using letters for variables please... Apr 22, 2019 at 22:19
  • @stuartdotnet: I do not dispute about the samurai example being better of worse, but why stop using one-letter variables? If variables have no particular meaning but are just placeholders, single-letter variables are much more compact and to the point. Using longer names like itemA or objectA just to make the name longer is not always better.
    – Giorgio
    Apr 23, 2019 at 8:51
  • 1
    Then you've missed my point - using non-descript names is hard to read, follow and understand, and is not a good way to explain a point Apr 25, 2019 at 21:23
  • @stuartdotnet: I do not think I have missed your point: You claim that descriptive names are always better and make code always more readable and self-explaining.
    – Giorgio
    Apr 26, 2019 at 10:40

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.