0

I am really interested in some architectural methods. I like DI and IOC, but I don't understand costructor injection; why is it so complicated. I've written the code below which uses constructor injection:

namespace DependencyInjection
{
    class Program
    {
        static void Main(string[] args)
        {
            ConstructorInjectionClass myCtx = new ConstructorInjectionClass(new PdfFormat());
            myCtx.Print();
            Console.Read();
        }
    }



    public interface IFormat
    {
        void Print();
    }

    public class PdfFormat : IFormat
    {

        public void Print()
        {
            Console.WriteLine("Pdf Format Print is completed...");
        }
    }


    // Constructor Injection

    public class ConstructorInjectionClass
    {
        private IFormat _format;

        public ConstructorInjectionClass(IFormat format)
        {
               _format = format;
        }

        public void Print()
        {
            _format.Print();
        }
    }

I've written some code below. I think it's simple.



    public interface IFormat
    {
        void Print();
    }

    public class PdfFormat : IFormat
    {

        public void Print()
        {
            Console.WriteLine("Pdf Format Print is completed...");
        }
    }

   public interface ISave
    {
        void Add();
    }

    public class Sql: ISave
    {

        public void Add()
        {
            Console.WriteLine("Adding to SQL is completed...");
        }
    }


    // Constructor Injection

    public class ConstructorInjectionClass
    {


        public ConstructorInjectionClass(IFormat format)
        {
               format.Print();
        }

         public ConstructorInjectionClass(ISave saver)
        {
              saver.Add();
        }



Why should I use constructor injection? Advantages or disadvantages of these two methods?

Sam Holder
  • 32,535
  • 13
  • 101
  • 181
loki
  • 2,926
  • 8
  • 62
  • 115

3 Answers3

4

The first example is constructor injection. You are injecting the class with the responsibility for printing into the class.

In the second example you are creating a new class with one of 2 arguments and using the argument in the constructor. This is bad for several reasons:

  • Your constructor should not really do significant work, this is either saving or printing in the constructor
  • Your different constructors are doing different this. The constructor should only create a new instance of your class.
  • It is not clear that the different constructors will actually do something when they are given different objects.
  • If you pass the objects to the constructor and then it just calls them, why would you not just have the code that is constructing this class call the methods on ISave and IPrint implementations. After all it must have them to be able to pass them to the method. If your object holds these internally then they could have been provided when your object was constructed (like in your composition root) and the client code that calls Print on your object would not need to know anything about the fact that the ISave and IPrint implementations exist,

Constructor injection is about you class asking for the dependencies it has in it's constructor, so it is clear what the dependencies are. By requiring the dependencies rather than creating them it becomes simpler to test the class as you can inject mock dependencies for testing purposes.

The first option is good, and if you want to add saving then you should add an extra argument to the constructor to take a ISave interface as well as the IPrint interface and have a method Save which will delegate to the ISave implmentation.

By having the dependencies injected and by programming to an interface it makes it easier to change the functionality later on. You could, for example, make it pring to a file easily (by changing the IPrint interface you pass in or change it to save to an xml file or a webservice by changing the ISave implementation you pass it. This make you class loosely coupled to the save and print implemenations

I would read this excellent answer for more guidance on DI/IOC

Community
  • 1
  • 1
Sam Holder
  • 32,535
  • 13
  • 101
  • 181
  • +1 Constructors should be simple: http://blog.ploeh.dk/2011/03/03/InjectionConstructorsShouldBeSimple.aspx – Mark Seemann Apr 03 '11 at 12:33
  • 1
    @Mark haha, was just adding a link to your excellent answer. Whilst I'm in no way affiliated with Mark Seemann I can recommend his [excellent book](http://www.manning.com/seemann/) – Sam Holder Apr 03 '11 at 12:34
4

Well, as with any pattern, constructor injection should be used when and only when it's a good idea to use it. Your example code is kind of strange...

  • Your first example is spot on. Your class has a method called Print which has a dependency on another class to do the printing. Rather than instantiate this dependency, it requires that the dependency be supplied in its constructor. This is a classic example of the Dependency Inversion Principle. Basically: "Require, don't instantiate."
  • Your second example isn't quite clear, though. What is your class really doing? What's it for? It has two constructors which perform an action on their dependencies, but why? Nowhere else in the class is there a dependency on instances of these types. So why have the wrapper class in the first place? It seems more... contrived... than your first example. It's unclear what the architecture of the code is trying to accomplish, and therefore as it stands not a good use of constructor injection.
David
  • 208,112
  • 36
  • 198
  • 279
  • can you explan with sample ? "Your first example is spot on. Your class has a method called Print which has a dependency on another class to do the printing. Rather than instantiate this dependency, it requires that the dependency be supplied in its constructor. This is a classic example of the Dependency Inversion Principle. Basically: "Require, don't instantiate."" – loki Apr 03 '11 at 12:30
  • i think: what is strange ? "Your class has a method called Print which has a dependency on another class to do the printing." – loki Apr 03 '11 at 12:32
  • @programmerist: Well, one example would be a class which interacts with a couple of database repositories. The class would have some methods which have lots of business logic and, based on that logic, makes changes to the database through a couple of repositories. Rather than instantiate those repositories internally, you can require that instances of them be supplied when constructing the class. This can be handled by an IoC framework (StructureMap is my personal favorite) or manually. For the purpose of the class, either will work. – David Apr 03 '11 at 12:34
  • @programmerist: I don't follow your second comment. What are you asking? – David Apr 03 '11 at 12:34
  • @David: some thing is wrong my first sample. you said that ; "Your class has a method called Print which has a dependency on another class to do the printing." what is the strange or wrong? Lokk sample : http://koraykirdinli.blogcu.com/tasarim-desenleri-loose-coupling-prensibi-esnek-bag/9077424 – loki Apr 03 '11 at 12:40
  • 1
    @programmerist: There's nothing wrong with your first example. It was your second example which was strange. Your first example was a classic example of dependency inversion by means of constructor injection. – David Apr 03 '11 at 12:43
1

Lets say that you want to inject dependencies... you could do this via constructor injection or via property setters. I think one of the advantages to constructor injection is that IOC's use this strategy. So if you aren't sure you want to go IOC but you want to do DI then should probably use constructor injection to make the transition to IOC latter... easier... if you should change your mind...

John Sobolewski
  • 4,512
  • 1
  • 20
  • 26