Back to: Design Patterns in C# With Real-Time Examples
Inversion of Control Using Factory Pattern in C# with Example
In this article, I am going to discuss how to achieve Inversion of Control using the Factory Design Pattern in C# with an example. Please read our previous article where we discussed the basics of Inversion of Control in C#.
What is Inversion of Control in C#?
The Inversion of Control (IoC) in C# is a design principle but some people also refer to it as a pattern. As the name suggests, it is used to invert the various types of controls in object-oriented design to achieve loose coupling between the classes. Here, control means any extra responsibilities a class has other than its main or fundamental responsibility, such as control over the flow of application execution, control over the flow of object creation or dependent object creation and binding, etc.
In simple words, we can say that the Inversion of Control (IoC) is a way to invert the flow of control of a system in comparison to standard procedural programming.
Example:
In procedural programming, a chunk of code that uses or consumes another chunk of code is in control of the process. It exactly knows what piece of code it uses and what method is present in a class. And in doing so, it may be possible that it knows some of the implementation details in the code it uses. An example of such a scenario is when a class, let’s say X uses another class, let’s say Y as shown in the below diagram.
As shown in the above diagram, class X needs to consume class Y to perform some tasks. That’s all good, but does class X really need to know that it uses class Y?
Isn’t it nice that class X knows that it uses something that has the behavior of Y, without knowing who actually implements the behavior?
By extracting an abstract definition of the behavior used by class X and letting the consumer class X use an instance of that instead of Y as shown in the below diagram.
In the above diagram, class Y implements interface I, and class X uses an instance of I instead of class Y. In the above implementation class X uses class Y but the interesting fact is that class X doesn’t know that. It just knows that it uses something that implements interface I.
That could be class Y, but it could also be P, Q, or R or any class that implements the interface I. So in this article, I will talk about the Inversion of Control (IoC) and how to implement it using some simple as well as real-time examples. This will be the first step towards achieving a loosely coupled design as shown in the below figure.
Let’s understand how the inversion of control inverts various types of control with some examples.
Control over the Flow of a Program:
As we know in a typical C# console application, the execution starts from the Main() method. The Main() method controls the flow of program execution.
Example: Understanding Program Execution Flow
Create a console application with the name “ControlFlowDemo” and copy and paste the below code into the Program class as shown below.
namespace ControlFlowDemo { class Program { static void Main(string[] args) { bool continueExecution = true; do { Console.Write("Enter Employee Name:"); var name = Console.ReadLine(); Console.Write("Enter Employee Department:"); var department = Console.ReadLine(); Console.Write("Enter Employee Salary:"); var salary = Console.ReadLine(); Console.Write("Do you want to save it to the Database ? Y/N: "); var DoYouWantToSaveToDB = Console.ReadLine(); if (DoYouWantToSaveToDB.ToUpper() == "Y") SaveToDatabase(name, department, salary); Console.Write("Do you want to Continue? Y/N: "); var wantToContinue = Console.ReadLine(); if (wantToContinue.ToUpper() == "N") continueExecution = false; } while (continueExecution); } private static void SaveToDatabase(string name, string department, string salary) { //Here we need to write code to save the employee details to database //Here we are only focusing on IoC not on writting any database related code } } }
In the above example, the Main() method of the Program class controls the flow of the application execution. It takes the user’s input for the Name, Department, and Salary of an employee. It saves the data by calling the SaveToDatabase() method by passing Name, Department, and Salary values, and then continues or not the console depending upon the user’s input. So here, the control flow of the application execution is managed by the Main() method.
Example: Control over the Dependent Object Creation
The Inversion of control can also be useful in the way we create objects of dependent classes. First of all, let’s understand what we mean by dependency here.
Consider the following example.
public class A { //Create one reference variable of type B B b; //Initializing the reference variable b through the constructor public A() { //initialize the variable with B class object b = new B(); } public void AClassMethod() { // do some task here //Call B Class method BClassMethod() b.BClassMethod(); // do some task here } } public class B { public void BClassMethod() { //do some task here } }
In the above example, class A calls b.BClassMethod() to complete its AClassMethod() task. So, in the above example, Class A cannot complete its task without class B and so here we can say that “Class A is dependent on class B” or “class B is a dependency of class A”.
In object-oriented programming, the classes need to be interacting with each other to complete their tasks as we saw in the above example. Class A creates and manages the lifetime of an object of class B. That means it controls the creation and lifetime of dependency class objects.
The Inversion of control (IoC) principle suggests inverting the control, which means we need to separate the dependency object creation logic into another class. In our example, we need to invert the dependency object creation control from class A to another class as shown in the below example.
public class A { B b; public A() { //initialize the variable with B class object b = Factory.GetObjectOfB(); } public void AClassMethod() { // do some task here //Call B Class method BClassMethod() b.BClassMethod(); // do some task here } } public class Factory { public static B GetObjectOfB() { return new B(); } } public class B { public void BClassMethod() { //do some task here } }
As you can see in the above example, class A uses the Factory class to get an object of class B. Thus, we have inverted the dependent object creation logic from class A to another class called Factory class. Class A is now no longer creates an object of class B instead it uses the Factory class to get the object of class B.
Let’s understand IoC using a real-time example.
In object-oriented design, we need to design the classes in a loosely coupled way. Loosely coupled means changes in one class should not force the other classes to change, so the whole application can become maintainable and extensible. Let’s understand this by using typical n-tier architecture as shown in the following figure.
Create an empty console application with the name IoC_DIP_DI_Demo as shown below.
Add a class file with the name Employee.cs and copy and paste the following code. Here we create a class with the name Employee having four properties such as ID, Name, Department, and Salary.
Employee.cs
namespace IoC_DIP_DI_Demo { public class Employee { public int ID { get; set; } public string Name { get; set; } public string Department { get; set; } public int Salary { get; set; } } }
Add a class file with the name EmployeeDataAccess.cs and copy and paste the following code. Here we create a class with one method called GetEmployeeDetails. This method is going to return the Employee Details by the ID of the Employee. In real-time you need to get the data from a data source but to simplify our example and to keep the focus on IoC here we hardcoded the Employee data.
EmployeeDataAccess.cs
namespace IoC_DIP_DI_Demo { public class EmployeeDataAccess { public Employee GetEmployeeDetails(int id) { // In real-time get the employee details from db //but here we are hard coded the employee details Employee emp = new Employee() { ID = id, Name = "Pranaya", Department = "IT", Salary = 10000 }; return emp; } } }
Add a class file with the name EmployeeBusinessLogic.cs and copy and paste the following code. As part of the Employee Business Logic class, we are creating the instance of EmployeeDataAccess and then calling the GetEmployeeDetails method and returning the EmployeeDetails.
EmployeeBusinessLogic.cs
namespace IoC_DIP_DI_Demo { public class EmployeeBusinessLogic { EmployeeDataAccess _EmployeeDataAccess; public EmployeeBusinessLogic() { _EmployeeDataAccess = new EmployeeDataAccess(); } public Employee GetEmployeeDetails(int id) { return _EmployeeDataAccess.GetEmployeeDetails(id); } } }
Finally, copy and paste the following code into the Program class. As part of the Main method, we are creating an instance of the EmployeeBusinessLogic and then Calling the GetEmployeeDetails method which will return the Employee Details. Once we get the Employee Details, we just print those details on the Console.
Program.cs
namespace IoC_DIP_DI_Demo { class Program { static void Main(string[] args) { EmployeeBusinessLogic BL = new EmployeeBusinessLogic(); Employee employeeDetails = BL.GetEmployeeDetails(1); Console.WriteLine(); Console.WriteLine("Employee Details:"); Console.WriteLine("ID : {0}, Name : {1}, Department : {2}, Salary : {3}", employeeDetails.ID, employeeDetails.Name, employeeDetails.Department, employeeDetails.Salary); Console.ReadKey(); } } }
Run the application and see the output as shown below.
Let’s understand the above code in detail:
As you can see in the above example, the EmployeeBusinessLogic class depends on the EmployeeDataAccess class. It creates an instance of the EmployeeDataAccess class in order to get the Employee data.
Now, let’s understand what’s wrong with the above class design.
In the above example, EmployeeBusinessLogic and EmployeeDataAccess classes are tightly coupled because the EmployeeBusinessLogic class creates an object of EmployeeDataAccess class and manages the lifetime of that object.
The EmployeeBusinessLogic and EmployeeDataAccess classes are tightly coupled classes. So, changes in the EmployeeDataAccess class will lead to changes in the EmployeeBusinessLogic class. For example, if we add, remove, or rename any method in the EmployeeDataAccess class then we need to change the EmployeeBusinessLogic class accordingly.
Suppose, in the future, the Employee data comes from different databases or web services, then we may need to create different classes for this, then it leads to changes in the EmployeeBusinessLogic class.
There may be multiple classes that use the EmployeeDataAccess class and create its object. So if we change the name of the EmployeeDataAccess class, then we need to find all the places in our source code where we create the objects of EmployeeDataAccess class and make the change. This is a repetitive code for creating an object of the same class and maintaining its dependencies.
Because of EmployeeBusinessLogic class creates an object of the concrete EmployeeDataAccess class; it is very difficult to be tested independently (TDD). The EmployeeDataAccess class cannot be replaced with a mock class.
So, to solve the above problems and to achieve a loosely coupled system, we can use IoC and DIP principles together.
The following pattern implements the IoC principle.
- Factory’
- Service Locator
- Dependency Injection
- Abstract Factory
Let’s use the Factory pattern to implement IoC in the above example as the first step towards attaining loosely coupled classes.
Add a class file with the name DataAccessFactory.cs and copy and paste the below code. The below factory class will create and return an instance of the EmployeeDataAccess class.
DataAccessFactory.cs
namespace IoC_DIP_DI_Demo { public class DataAccessFactory { public static EmployeeDataAccess GetEmployeeDataAccessObj() { return new EmployeeDataAccess(); } } }
Now, use this DataAccessFactory class in EmployeeBusinessLogic class to get an object of EmployeeDataAccess class.
Modify the EmployeeBusinessLogic class as shown below
namespace IoC_DIP_DI_Demo { public class EmployeeBusinessLogic { EmployeeDataAccess _EmployeeDataAccess; public EmployeeBusinessLogic() { _EmployeeDataAccess = DataAccessFactory.GetEmployeeDataAccessObj(); } public Employee GetEmployeeDetails(int id) { return _EmployeeDataAccess.GetEmployeeDetails(id); } } }
Run the application and see if everything is working as expected.
Let’s understand what we have done here.
As you can see, the EmployeeBusinessLogic class uses DataAccessFactory.GetCustomerEmployeeDataAccessObj() method to get an object of the EmployeeDataAccess class instead of creating it using the new keyword. Thus, we have inverted the control of creating an object of the dependent class from the EmployeeBusinessLogic class to the DataAccessFactory class.
This is a simple implementation of IoC and the first step towards achieving the fully loose coupled design. As we already discussed we will not achieve complete loosely coupled classes by only using IoC. Along with IoC we also need to use DIP, Strategy pattern, and DI (Dependency Injection).
In the next article, we will move to the second step to understand DIP and how it helps in achieving a loosely coupled design using a real-time example. Here, in this article, I try to explain the Inversion of Control using Factory Pattern in C# with an example. I hope this Inversion of Control using Factory Pattern in C# article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this Inversion of Control using Factory Pattern in C# article.
How EmployeeBusinessLogic does not affected if we rename the function name of GetEmployeeDetails(id) something else
or add one paramete more if we using Factory patten
Please reply me sir i am curious about whole thing
How are you passing id parameter to GetEmployeeDetails(id)? Thanks
awesome