Dependency Injection in C Sharp(C#)

Hello..!! Welcome back to The Midnight Coder..

Today we will discuss about an interesting topic called "Dependency Injection". So, Dependency Injection is a powerful Injection which kills the insects,bacteria and virus(Corona) in our stomach..😼😼😼 Just kidding


Will go step by step. For simplicity and to save some energy I will call  it as DI



Download C# code samples here

This topic makes bit confusion. So, Before continuing further I need some Deals/Promises to be clear. So that you can understand the concept of DI easily.
  1. Yes, but I can do this in a different way
  2. Is this the only way ?
  3. I won't do that
So, Don't ask these yourself in middle of this article to avoid confusion. Just go with the flow, implement it. You will definitely find the difference

What is DI

There are few definitions for DI. I've tried to make it simple below

"DI is a process of removing dependency of an object inside the class and injecting it(dependency) from the external/calling object"


So it is a Design Principle where we remove the static dependency of an object and injecting the dependency dynamically


Simply, one class/method is completely depending on another class/method, our job is to remove that dependency

Awwe..? what are all these confusing objects, classes, methods..?? We will crack it soon


Why DI ?

Our application code should be clean, testable and easily maintainable/extensible. Our classes/methods should be responsible for single functionality and Every time a functional requirement/modification comes, every time we should not modify our Server code

Once the service code ready, it should be testable with our own mocking methods without disturbing/deviating the actual flow of application. So this way, we can maintain our application efficiently in a long run.


Every class in our code should be open for extension, because we can't anticipate future requirements of application


Sample problem and Code

Problem Statement:

"We need to develop a Payment module for an e-commerce site. User will add items to cart, total payment amount will be calculated and redirected to Payment Gateway and pays with Card(Credit/Debit)"

CardPaymentService:

ProcessPayment is a method which communicates with Bank Servers/APIs, does the transaction and returns a Transaction Number 


    public class CardPaymentService
    {
        // Takes payable amount and receiver details
        // deduct the amount and returns transaction number
        public string ProcessPayment(decimal payableAmount,string receiverDetails)
        {
            // Actual transaction with bank servers
            // Deduct amount from Card and transfers it to receiver
            return "TRANS_C_0010";
        }
    }

PaymentMainClass:

This is the central server class. In MakePayment all the business logic will be validated and payment will be initiated to use CardPaymentService

public class PaymentMainClass
{
        public string MakePayment(decimal payableAmount, string receiverDetails)
        {
            // Checks for Business Logic and Initialize card payment service
            // Here MakePayment method is completely Depending on Card Service
            CardPaymentService cardService = new CardPaymentService();
    return cardService.ProcessPayment(payableAmount,receiverDetails);
        }
}

**Point to be noted Your Honour...!! Above class is completely depending on CardPaymentService - This is completely against the Article DI **

Below is UI Code - Console App in this case


public class ClientProgram
{
        static void Main(string[] args)
        {
            string orderedItems= "jeans,shoes";
            decimal totalOrderAmount = 2500;
            string receiverDetails = "Acc/Card number";
            // Redirecting to Payment Process
            PaymentMainClass paymentProcess = new PaymentMainClass();
            string transactionNumber = paymentProcess.MakePayment(totalOrderAmount, receiverDetails);
            Console.WriteLine("Payment Successful, Transaction Number :" + transactionNumber);
        }
}
Here user added two items to cart and the total amount was 2500(non-branded items may be πŸ‘…πŸ‘…). We are redirecting the user to Payment Gateway by passing total amount payable and receiver details. Payment will be done and Transaction number will be returned.. 

"Yayyy.. !! Getting new shoes and jeans."

But after some time, client asked us to allow the user to pay through GooglePay(very famous for scratch cards, but better luck every time where user will choose payment method from UI while doing payment

Then, we can simply Modify the code like below. Follow carefully..

1. Add new  class  - GooglePaymentService 


public class GooglePaymentService
{
public string ProcessPayment(decimal payableAmount,string receiverDetails)
        {
// Deduct amount from Linked bank account and transfers it to receiver
return "TRANS_GP_0025";
        }
}



2. Add if conditions in PaymentMainClass like below


public string MakePayment(decimal payableAmount, string receiverDetails, string paymentType)
{
            string transactionNumber = string.Empty;
            if (paymentType == "Card")
            {
                CardPaymentService cardService = new CardPaymentService();
                transactionNumber = cardService.ProcessPayment(payableAmount, receiverDetails);
            }
            else
            {
                GooglePaymentService googlePayment = new GooglePaymentService();
                transactionNumber = googlePayment.ProcessPayment(payableAmount, receiverDetails);
            }
            return transactionNumber;
}

3. In ClientProgram Need to pass new argument mentioning the payment Method

string paymentMethod = "GooglePay";

string transactionNumber = paymentProcess.MakePayment(totalOrderAmount, receiverDetails, paymentMethod);

Done... And every time a  requirement comes(PhonePe/NetBanking), we just need to add if-else/switch cases in  PaymentMainClass and simply release it to the client

Yesss..!! We've achieved it.. Client is very happy.. πŸ’ͺπŸ’ͺ Let's Party hard.. πŸŽ‰πŸŽ‰πŸŽ‰

βœ‹πŸ™‹πŸ™‹HOLD ON...!!! Think about below questions  

  1. Is it good to change the central class every time  ?
  2. Is your code testable without hitting the actual servers ?
  3. Is your code loosely coupled where you can break it into independent modules without any issues ?
  4. Will you easily maintain this type of code for multiple clients ?

DI will answer all your questions. 
It reduces modification of existing code for new requirements/features
Makes your code testable by injecting dummy payment objects
Mainly it removes the dependency between objects..(Freedom is much needed)
By this kind of modular approach you can easily maintain the code base in a long run and for multiple clients

So, Let's implement it by introducing an Interface called IPaymentService. It is having one method called ProcessPayment which takes amount and receiver details and returns a string(Transaction Number ) 


public interface IPaymentService
{
string ProcessPayment(decimal payableAmount, string receiverDetails);
}

We will implement this interface in all the different payment service classes (Card, GPay, PhonePe)


public class GooglePaymentService: IPaymentService

public class CardPaymentService: IPaymentService

Below are the types in DI. Will implement the code to remove our dependency by each type and how to use it from ClientProgram

Types of DI 

1. Constructor Injection

We inject/pass the dependency to PaymentMainClass through it's constructor.Then will call ProcessPayment through injected object

Now PaymentMainClass  looks like


public class PaymentMainClass
{
IPaymentService actualPaymentService = null;
public PaymentMainClass(IPaymentService paymentService)
{
            actualPaymentService = paymentService;
        }
        public string MakePayment(decimal payableAmount, string receiverDetails)
        {
            return actualPaymentService.ProcessPayment(
                  payableAmount, receiverDetails);
        }
}

 Here our Central code is Free from dependency. No If-else/switch, still it can process any type of payments which implements IPaymentService without the central code being modified. actualPaymentService holds/references the instance of the object which implements it's type, this instance is decided at run time instead of compile time(Static Dependency

Usage: ClientProgram

PaymentMainClass paymentProcess = new PaymentMainClass(new CardPaymentService());


string transactionNumber = paymentProcess.MakePayment(totalOrderAmount, receiverDetails);

Payment method will be decided on run time. Means while instantiating the central service, but in initial version PaymentMainClass  statically depended on Card/GPay services

2. Method Injection

Constructor injection will be helpful where all the methods in that class uses one/similar type of service(IPaymentService). But if there is a case where each method in that class used different type of services then it will be complex to create that many constructors as above.

So, We inject/pass the dependency to PaymentMainClass through the method.

Now PaymentMainClass  looks like

public class PaymentMainClass
{
        public string MakePayment(decimal payableAmount, string receiverDetails, IPaymentService paymentService)
        {
            return paymentService.ProcessPayment(payableAmount, receiverDetails);
        }
}

We need to add this as a argument to the calling method and use that instance to invoke the service methods directly. Then there will be no actualPaymentService and  PaymentMainClass as in Constructor Injection

Usage: ClientProgram

PaymentMainClass paymentProcess = new PaymentMainClass();

string transactionNumber = paymentProcess.MakePayment(totalOrderAmount, receiverDetails,new GooglePaymentService());

We inject the dependency while calling the service method  

3. Property Injection

We inject/pass the dependency to PaymentMainClass through it's public property. Generally we use encapsulation here. First we inject the dependency to the class property then we call the method. Mostly Property injection looks like Constructor injection.

Now PaymentMainClass  looks like


public class PaymentMainClass
{
        private IPaymentService _paymentService;
public IPaymentService PublicPaymentService
{
            get { return _paymentService; }
            set { _paymentService = value; }
  }
public string MakePayment(decimal payableAmount, , string receiverDetails)
        {
            return _paymentService.ProcessPayment(payableAmount, receiverDetails);
        }    
}



Usage: ClientProgram

PaymentMainClass paymentProcess = new PaymentMainClass();
paymentProcess.PublicPaymentService = new GooglePaymentService();
string transactionNumber = paymentProcess.MakePayment(totalOrderAmount, receiverDetails);

Download C# code samples here

I hope you got an idea on the beauty of  "Dependency Injection"
We got our freedomπŸ’ͺ from dependency.. It's time to party πŸŽ‰πŸŽ‰..

Thanks for your patience. Stay tuned for latest updates on The Midnight Coder

Go to Top

Comments

Popular posts from this blog

What is .Net, ASP.Net and MVC.Net ?

ASP.NET Web API with C# - Implementing GET method and accessing in C#,JQuery