Introduction
Dependency Injection (DI) is a pattern where objects are not responsible for creating their own dependencies. Dependency injection is a way to remove hard-coded dependencies among objects, making it easier to replace an object's dependencies, either for testing (using mock objects in unit test) or to change run-time behavior.
Before understanding Dependency Injection you should be familiar with the two concepts of Object Oriented Programming, one is tight coupling and another is loose coupling, so let's see each one by one.
Tight Coupling: When a class is dependent on a concrete dependency, it is said to be tightly coupled to that class. A tightly coupled object is dependent on another object; that means changing one object in a tightly coupled application often requires changes to a number of other objects. It is not difficult when an application is small but in an enterprise level application it is too difficult to make the changes.
Loose Coupling: It means two objects are independent and an object can use another object without being dependent on it. It is a design goal that seeks to reduce the inter- dependencies among components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
Now in short, Dependency Injection is a pattern that makes objects loosely coupled instead of tightly coupled. In this article you will be the first to introduce tight coupling and thereafter you will introduce loose coupling using the Constructor Dependency Injection Pattern. So let's see that.
Using the Code
To understand the concept of Dependency Injection, create an example that is the Error Log Management. The Error Log Management example describes how to create an error log for the application. There are two types of log management, one is using a text file and the other is uses an event viewer.
First of all create an interface IErrorLogger that has one method to write the error log. This interface will be inherited by other log classes.
- using System;
- namespace DependencyInjection
- {
- public interface IErrorLogger
- {
- void LogMessage(Exception ex);
- }
- }
- using System;
- using System.Configuration;
- using System.IO;
- namespace DependencyInjection
- {
- public class FileLogger : IErrorLogger
- {
- public void LogMessage(Exception ex)
- {
- string folderPath = ConfigurationManager.AppSettings["ErrorFolder"];
- if (!(Directory.Exists(folderPath)))
- {
- Directory.CreateDirectory(folderPath);
- }
- FileStream objFileStrome = new FileStream(folderPath + "errlog.txt", FileMode.Append, FileAccess.Write);
- StreamWriter objStreamWriter = new StreamWriter(objFileStrome);
- objStreamWriter.Write("Message: " + ex.Message);
- objStreamWriter.Write("StackTrace: " + ex.StackTrace);
- objStreamWriter.Write("Date/Time: " + DateTime.Now.ToString());
- objStreamWriter.Write("============================================");
- objStreamWriter.Close();
- objFileStrome.Close();
- }
- }
- }
- using System;
- using System.Configuration;
- using System.Diagnostics;
- namespace DependencyInjection
- {
- public class EventViewerLogger : IErrorLogger
- {
- public void LogMessage(Exception ex)
- {
- EventLog objEventLog = new EventLog();
- string sourceName = ConfigurationManager.AppSettings["App"];
- string logName = ConfigurationManager.AppSettings["LogName"];
- if (!(EventLog.SourceExists(sourceName)))
- {
- EventLog.CreateEventSource(sourceName, logName);
- }
- objEventLog.Source = sourceName;
- string message = String.Format("Message: {0} \n StackTrace: {1} \n Date/Time: {2} ", ex.Message, ex.StackTrace, DateTime.Now.ToString());
- objEventLog.WriteEntry(message, EventLogEntryType.Error);
- }
- }
- }
- using System;
- namespace DependencyInjection
- {
- public class Operation
- {
- IErrorLogger logger = new FileLogger();
- public void Division()
- {
- try
- {
- int firstNumber = 15, secondNumber = 0, result;
- result = firstNumber / secondNumber;
- Console.WriteLine("Result is :{0}", result);
- }
- catch (DivideByZeroException ex)
- {
- logger.LogMessage(ex);
- }
- }
- }
- }
Now call your class method in your application startup class and you get a log in the text file so your start up class code is below.
- using System;
- namespace DependencyInjection
- {
- class Program
- {
- static void Main(string[] args)
- {
- Operation objOperation = new Operation();
- objOperation.Division();
- Console.Read();
- }
- }
- }

Figure 1.1 Error Log in txt File
To solve this problem you should use constructor dependency injection in which an IErrorLogger is injected into the object.
Constructor Dependency Injection Pattern
This is the most commonly used Dependency Pattern in Object Oriented Programming. The Constructor Injection uses a parameter to inject dependencies so there is normally one parameterized constructor always. So in this constructor dependency the object has no default constructor and you need to pass specified values at the time of creation to initiate the object.
You can say that your design is loosely coupled with the use of constructor dependency injection.
Now create a class OperationEvent. That class has a parameter constructor. This constructor will be used to inject dependencies in the object. Let's see the following code.
- using System;
- namespace DependencyInjection
- {
- public class OperationEvent
- {
- IErrorLogger logger;
- public OperationEvent(IErrorLogger logger)
- {
- this.logger = logger;
- }
- public void Division()
- {
- try
- {
- int firstNumber = 15, secondNumber = 0, result;
- result = firstNumber / secondNumber;
- Console.WriteLine("Result is :{0}", result);
- }
- catch (DivideByZeroException ex)
- {
- logger.LogMessage(ex);
- }
- }
- }
- }
- using System;
- namespace DependencyInjection
- {
- class Program
- {
- static void Main(string[] args)
- {
- OperationEvent objOperationEvent = new OperationEvent(new EventViewerLogger());
- objOperationEvent.Division();
- Console.Read();
- }
- }
- }

Figure 1.2 Log Errors in Event Viewer.
Conclusion
This article has introduced a basic object oriented concept such as tight coupling and loose coupling. I hope you also get an idea of how to manage your application error log and finally you have learned about Constructor Dependency Injection Pattern. I hope it will be helpful for you and if you have any doubt or feedback then post your comments here or you can directly connect to me by https://twitter.com/ss_shekhawat.

Sumit SharmaPosted Sep 8, 2018, 5:50 AM
Well Explained!
var kumarPosted Mar 22, 2018, 2:22 AM
Can i use class instead of interface. http://rextester.com/WTW14311
Gowtham RajamanickamPosted Mar 13, 2015, 5:23 AM
Good article !
Ramesh beruguPosted Dec 26, 2014, 1:16 AM
Can we pass EventViewerLogger and FileLogger in the form of List<IErrorLogger> to log info at more than one place, like public OperationEvent(IErrorLogger logger) { this.logger = logger; }
Sagar NanivadekarPosted Dec 10, 2014, 1:13 AM
how when we want to log to both file and event log ?
Ramesh beruguPosted Oct 7, 2014, 10:58 PM
How can we implement if we want to log exceptions into files and event viewer as well ?
Sandeep Singh ShekhawatPosted May 28, 2014, 2:19 AM
What do you think that how this code can't resolve ?
Akhil MittalPosted May 28, 2014, 1:31 AM
Does this code resolve the dependency fully???