. net IOC schema dependency inversion (DIP), inversion of control (IOC), dependency injection (DI)

Time:2020-7-30

Dependency Inversion Principle (DIP)

Dependency Inversion Principle (DIP) is one of the six basic principles of object-oriented. It refers to a specific form of decoupling, which makes the high-level module independent of the implementation details of the low-level module, and the dependency relationship is reversed (reversed), so that the low-level module depends on the requirement abstraction of the high-level module

The principle stipulates that:

  • High level module should not depend on low level module, both should depend on its abstract interface
  • Abstract interface should not depend on concrete implementation, while concrete implementation should depend on abstract interface

Let’s take a look at a simple underground order process to send related SMS or e-mails to our users


public SendingEmail
{
 public void Send(string message){
  //do something
 }
}

public Ordering
{
 SendingEmail _sendingEmail=null;
 public void Order(string message){
  //Order business operation
  if(_sendingEmail == null)
  {
   _sendingEmail=new SendingEmail();
  }
  _sendingEmail.Send(message);
 }
}

In this way, our code is OK. At present, as long as we have completed the order operation, the sending function will be triggered. However, it violates the dip because the ordering class depends on the sendingemail class, while the sendingemail class is not an abstract class, but a concrete class. Let’s think about another example. If the business man comes to us at this time and puts forward a new requirement, Ask us to change to SMS instead of email, so how do we need to change it?


public class SendingSMS
{
 public void Send(string message){
  //do something
 }
}
public Ordering
{
 SendingEmail _sendingEmail=null;
 SendingSMS _sendingSMS=null;
 bool isSendingSMS=true;
 public void Order(string message){
  //Order business operation
  if(isSendingSMS){
   if(_sendingSMS == null)
   {
    _sendingSMS=new SendingSMS();
   }
   _sendingSMS.Send(message);
  }else{
   if(_sendingEmail == null)
   {
    _sendingEmail=new SendingEmail();
   }
   _sendingEmail.Send(message);
  }
  
 }
}

According to the above requirements, we have to create more classes and declare them in the ordering class. Finally, we need to use the if else statement to decide whether to use SMS or e-mail. However, when we have more such processing operations, it may be more confusing than now, which means that we must declare more new concrete class instances in the ordering class

We need to pull out a way to let the high-level module rely on the abstraction and use it instead of our implementation class, which will map to the implementation class

Inversion of control (IOC)

Inversion of control (IOC) is an object-oriented design principle. It can help us make the high-level module rely on the abstract rather than the concrete implementation of the underlying module. In other words, it helps to implement (Dependency Inversion Principle – dip)

public interface ICustomerCommunication
{
 void Send(string message);
}
Then we modify the sendingemail and sendingsms classes to inherit from the icustomercommunication interface

public class SendingEmail:ICustomerCommunication
{
 public void Send(string message){
  //do something
 }
}

public class SendingSMS:ICustomerCommunication
{
 public void Send(string message){
  //do something
 }
}

Let’s modify the ordering class to use the abstract interface


public Ordering
{
 ICustomerCommunication _customerComm=null;
 bool isSendingSMS=true;
 public void Order(string message){
  //Order business operation
  if(isSendingSMS){
   if(_customerComm == null)
   {
    _customerComm=new SendingSMS();
   }
   _customerComm.Send(message);
  }else{
   if(_customerComm == null)
   {
    _customerComm=new SendingEmail();
   }
   _customerComm.Send(message);
  }
  
 }
}

Through the above modification, our inversion of control is more in line with dip

Dependency injection (DI)

Dependency injection (DI) is a way to realize inversion of control

  • Constructor Inject
  • Method injection
  • Attribute injection

Although we have implemented IOC through the above code, and the ordering class relies on the icustomercommunication abstraction, we still use the implementation class in the ordering class, which makes it impossible for us to completely decouple between classes


 if(isSendingSMS){
 if(_customerComm == null)
 {
  _customerComm=new SendingSMS();
 }
  _customerComm.Send(message);
 }else{
  if(_customerComm == null)
  {
   _customerComm=new SendingEmail();
  }
  _customerComm.Send(message);
 }

Let’s talk about Di, which helps us to inject implementation into abstract classes (icustomercommunication interface). Di mainly reduces the coupling between classes and removes the dependency classes from the binding between abstract and concrete implementations

Constructor Inject

Through constructor injection, we pass the object that implements the class to the constructor of the dependent class and assign it to this interface


public class Ordering
{
 ICustomerCommunication _customerComm=null;
 public Ordering(ICustomerCommunication customerComm){
  _customerComm=customerComm;
 }
 public void Order(string message){
  _customerComm.Send(message);
 }
}

In the above code, the constructor uses the implementation class object to bind to the interface. If we pass the implementation of sendingsms to this class, all we have to do is declare an instance of the sendingsms class, and then pass it to the ordering constructor, as follows:

Method injection

By using constructor injection, we will have to use an instance of the implementation class, sendingsms or sendingemail, for the lifetime of the ordering class. Now, if you want to pass an instance of the implementation class every time you call the method, you must use method injection


public class Ordering
{
 public void Order(ICustomerCommunication customerComm,string message){
  _customerComm=customerComm;
  _customerComm.Send(message);
 }
}

The call method is as follows


SendingSMS sendingSMS=new SendingSMS();
Ordering ordering=new Ordering(sendingSMS);
ordering.Order(sendingSMS,"msg");

Attribute injection

From the above description, we know that the constructor injection method uses the dependency class in the whole life cycle, and the method injection directly limits our injection to the method, and then we will learn about the property injection


public class Ordering
{
 public ICustomerCommunication customerComm {get;set;}
 public void Order(string message){
  _customerComm.Send(message);
 }
}

The call method is as follows


SendingSMS sendingSMS=new SendingSMS();
Ordering ordering=new Ordering(sendingSMS);
ordering.customerComm=sendingSMS;
ordering.Order("msg");

In fact, constructor injection is the most commonly used method to implement di. If you need to pass different dependencies on each method call, you can use method injection, and the use of property injection is relatively small

Reference

https://zh.wikipedia.org/wiki/ Inversion of control

https://zh.wikipedia.org/zh-hans/ Dependency Inversion Principle

This article about. Net IOC pattern dependency inversion (DIP), inversion of control (IOC), dependency injection (DI) article introduced here, more related. Net IOC schema dependency inversion, inversion of control, dependency injection content, please search the previous articles of developeppaer or continue to browse the related articles below, I hope you can support developeppaer more in the future!