Dependency Injection

Dependency Injection mainly reduces the tight coupling between the classes. Dependency Injection moves the abstraction binding out of the class or higher level modules. By Dependency Injection, we can achieve the process of removing the dependency of low level modules from higher level modules. Dependency Injection can be achieved in three ways, which are shown below.

  • Dependency Injection via Constructor Injection.
  • Dependency Injection via Method Injection.
  • Dependency Injection via Property Injection.

Dependency Injection via Constructor Injection

Problem

Lets have three low level classes or modules.

  1. //first Low level class
  2. class Sum
  3. {
  4. public void func(int a, int b)
  5. {
  6. //return a + b;
  7. Console.WriteLine(a + b);
  8. }
  9. }
  10. //second Low level class
  11. class Subtract
  12. {
  13. public void func(int a, int b)
  14. {
  15. Console.WriteLine(a - b);
  16. }
  17. }
  18. //third Low level class
  19. class Multiple
  20. {
  21. public void func(int a, int b)
  22. {
  23. Console.WriteLine(a * b);
  24. }
  25. }

Higher Level Module

  1. class HighlevelModule
  2. {
  3. //DependencyInterface Action = null;
  4. Sum s = null;
  5. public void funcWrite(int a, int b)
  6. {
  7. s.func(a, b); //here hig level module depends on low level module
  8. }
  9. // for calling sub or mul we have to create instances and dependency is there
  10. }

What problem can we have?

This design is against the DIP Dependency Inversion Principle. Class HighlevelModule depends on class Sum, which is a low level class. We can call “Subtract” and “mul” classes also like this, but we will use only one object at a time. Using this, we have to use all the objects at the same time, which we don’t want to use. For this, we have used the approach given below by Dependency Injection to achieve this.

Interface for Dependency Injection
  1. //Interface for dependency Injection
  2. interface IDependencyInterface
  3. {
  4. void func(int a, int b);
  5. }
Low Level Modules
  1. //first Low level class
  2. class Sum :IDependencyInterface
  3. {
  4. public void func(int a, int b)
  5. {
  6. //return a + b;
  7. Console.WriteLine(a + b);
  8. }
  9. }
  10. //second Low level class
  11. class Subtract : IDependencyInterface
  12. {
  13. public void func(int a, int b)
  14. {
  15. Console.WriteLine(a - b);
  16. }
  17. }
  18. //third Low level class
  19. class Multiple : IDependencyInterface
  20. {
  21. public void func(int a, int b)
  22. {
  23. Console.WriteLine(a * b);
  24. }
  25. }
High level Module
  1. //high Level module
  2. class HighlevelModule
  3. {
  4. IDependencyInterface action = null;
  5. // Sum s = null;
  6. //Constructor
  7. //Dependency Injection via constructor
  8. public HighlevelModule(IDependencyInterface act)
  9. {
  10. this.action = act;
  11. }
  12. public void Actionfunc(int a, int b)
  13. {
  14. action.func(a, b);
  15. }
  16. }

We will call the method, which we require, as shown below.

  1. static void Main(string[] args)
  2. {
  3. Sum s = new Sum();
  4. HighlevelModule high = new HighlevelModule(s);
  5. s.func(6, 5);
  6. Console.Read();
  7. }

Hence, there is no dependency now. Higher level module is not dependent on low level ones. We have done the Constructor Injection, while we are injecting the dependency in constructor only.

Output
Dependency Injection via Method Injection

In this type of injection, the dependent object is injected, using the method of the class. In Constructor Injection, the dependent class uses the same concrete class for its all life time and if we have to pass some separate concrete class on each invocation of the method, at this moment, we have to pass the dependency in method only and not in constructor.

In Method Injection, we pass the object of the concrete class into the method of the dependent class.

Here, we pass the object of the class, which we want to use, which may be Sum, Subtract or Multiple into the method of HighlevelModuleM class (method's name is Actionfunc).We have to pass the object of the concrete class and the parameters used.

The example of the Method Injection is given below.
  1. class MethodInjection
  2. {
  3. static void Main(string[] args)
  4. {
  5. Sum s = new Sum();
  6. HighlevelModuleM high = new HighlevelModuleM();
  7. high.Actionfunc(s, 5, 6);
  8. //s.Actionfunc
  9. //s.funct(6, 5);
  10. Console.Read();
  11. }
  12. }
  13. //high Level module
  14. class HighlevelModuleM
  15. {
  16. IDependencyInterface actionM = null;
  17. // Sum s = null;
  18. //Constructor
  19. //Dependency Injection via constructor
  20. //public HighlevelModule(IDependencyInterface act)
  21. //{
  22. // this.action = act;
  23. //}
  24. //Method Injection
  25. public void Actionfunc(IDependencyInterface act, int a, int b)
  26. {
  27. this.actionM = act;
  28. actionM.funct(a, b);
  29. }
  30. }
  31. interface IDependencyInterface
  32. {
  33. void funct(int a, int b);
  34. }
  35. class Sum : IDependencyInterface
  36. {
  37. public void funct(int a, int b)
  38. {
  39. //return a + b;
  40. Console.WriteLine(a + b);
  41. }
  42. }
  43. //second Low level class
  44. class Subtract : IDependencyInterface
  45. {
  46. public void funct(int a, int b)
  47. {
  48. Console.WriteLine(a - b);
  49. }
  50. }
  51. //third Low level class
  52. class Multiple : IDependencyInterface
  53. {
  54. public void funct(int a, int b)
  55. {
  56. Console.WriteLine(a * b);
  57. }
  58. }
Here, we are passing the object of the Sum Class s and the parameters 5 and 6.
  1. public void Actionfunc(IDependencyInterface act, int a, int b)
  2. {
  3. this.actionM = act;
  4. actionM.funct(a, b);
  5. }
  6. //Calling Or Intializing
  7. Sum s = new Sum();
  8. HighlevelModuleM high = new HighlevelModuleM();
  9. high.Actionfunc(s, 5, 6);
If we want to use any other class other than Sum, we can pass the object of that class here.
Output


Property Injection

As we have seen in the two cases, mentioned above, In Constructor Injection Dependent class, we will use one concrete class for the entire life time and the in Method Injection, we will pass the object of the concrete class into the method of the dependent class.

In a case, when both the concrete classes and the high level modules are in different places (modules), how can we achieve the Dependency Injection? This brings us to the part of Property Injection.

In Property Injection, we will have a setter property in the High Level Module/ Dependent class and we will pass the object of the concrete class via this setter property. In this type, the setter property of the dependent class will take the object of the concrete class and pass it to the Interface used by the class.

  1. class PropertyInjection
  2. {
  3. static void Main(string[] args)
  4. {
  5. SumP s = new SumP();
  6. HighlevelModuleP high = new HighlevelModuleP();
  7. high.ActionP = s;
  8. high.Actionfunc(3, 4);
  9. Console.Read();
  10. }
  11. }
  12. //high Level module
  13. class HighlevelModuleP
  14. {
  15. IDependencyInterfaceP actionP = null;
  16. //Propert Setter where this property will be set by Object of the class
  17. public IDependencyInterfaceP ActionP
  18. {
  19. get
  20. {
  21. return actionP;
  22. }
  23. set
  24. {
  25. actionP = value;
  26. }
  27. }
  28. //Method Injection
  29. public void Actionfunc(int a, int b)
  30. {
  31. actionP.functP(a, b);
  32. }
  33. }
  34. interface IDependencyInterfaceP
  35. {
  36. void functP(int a, int b);
  37. }
  38. class SumP : IDependencyInterfaceP
  39. {
  40. public void functP(int a, int b)
  41. {
  42. //return a + b;
  43. Console.WriteLine(a + b);
  44. }
  45. }
  46. //second Low level class
  47. class SubtractP : IDependencyInterfaceP
  48. {
  49. public void functP(int a, int b)
  50. {
  51. Console.WriteLine(a - b);
  52. }
  53. }
  54. //third Low level class
  55. class MultipleP : IDependencyInterfaceP
  56. {
  57. public void functP(int a, int b)
  58. {
  59. Console.WriteLine(a * b);
  60. }
  61. }

The output of this will be, as shown below.

Property Injection is also called Setter Injection.
Attached is the source code in C# for Dependency injection (Constructor, Method and Property Injection).