What are Inversion of Control (IoC), DIP, DI, and IoC Container?

Many developers are confused about DIP, IoC, DI, and IoC Container. Well, we've been using the concept even the from the DOS mode era. It’s only when SOLID OOP Design and Design Patterns were introduced that made this popular. It is the D in the SOLID acronym which stands for Dependency Inversion Principle. New concepts were added of course.

What are these Acronyms?
IoC Inversion of Control
DIP Dependency Inversion Principle
DI Dependency Injection

In order to understand these, let’s take a look at the key terms.

Key Terms:

Dependency Inversion Principle
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions.
- Agile Principles, Patterns, and Practices in C#

Benefits from DIP?
  • Software Architecture such as DDD, Domain Centric Driven Design, SOLID OOP Design and Design Patterns use this concept to leverage requirements of changing technologies.
  • Allow our application to use different kind of algorithms, data store, etc;
  • Multiple implementation instead of chain inheritance;
  • Easier to test by injecting fakes or Moqs.
Inversion of Control

These are the patterns that implementing DIP.

Uses of Inversion of Control:
  • It decouples dependencies between high-level and low-level layers through shared abstractions.
  • Acts as an interface between two system or components.
  • It controls over the flow of an application
  • It controls the dependency creation and bindings

Kinds of Inversion of Controls
  1. Interface Inversion
  2. Most of the time when we implement DIP we use interface. This is a good design. When we expect that high-level modules will be depending on several dependencies, we should invert these dependencies by  adding another layer of abstraction using interface. In these manner we could easily swap these dependencies.

    Eg: In Domain Driven Design, the Core Domain is the brain of the application. The Data Layer, UI Layer, Sub Domains, Presentation Layer, and Test will be dependent on the Core Domain. This is typical DIP example in which we avoided the Business Layer to be dependent on the Data Layer. By doing this, we can swap any database provider we want even in-memory database collections. We can also extend our application to be expose on Web, desktop, WCF, or Web Services. We can also test our application by injecting in-memory fake data.

  3. Flow Inversion
  4. During the DOS mode era under programming 101, we used procedural UI interface (eg. Enter your Name[name], enter key, Enter your Course[course] ). The user must press the enter key to show the next entry and this is a problem. Flow Inversion allow the user to navigate through the field of entries before finally saving it.

  5. Dependency Creation/Binding Inversion
  6. Dependency Creation is another way of implementing DIP. We can invert the control by creating objects outside the class they are being used in. Meaning, objects are already created before injecting to the class that uses it. The advantage of using this approach is that we easily swap any object we want to inject.
Dependency Creation In Focus
Let's focus out attention to Dependency Creation and see how to implement them. There are lots of patterns that implement these concept but we will discussing the commonly used patterns.
  1. Dependency Inversion
  2. This is the most popular way of implementing DIP. When we think about DIP we think about DI.

    3 ways to Implement DI

    • Constructor Injection
    • This is the most common DI where dependencies are pass to dependent via constructor.

      Eg: In the example below, we have a class that can use different kind of encryption algorithm. So we want to inject that algorithm the moment we call the Encrypt class.
      To inject the dependency, we create the object and pass on calling class.
    • Setter Injection/Property Injection
    • To implement Setter Injection, use the properties to hold the dependencies. When using Setter, make the property public. 
      Eg: To inject the dependency, we must set the object to the property.

    • Interface Injection
    • Another way to implement Inversion is through Interface Injection. Looking at the code, it sounds like a Method Injection.

  3. Factory Pattern, Service Locator Pattern, and other patterns
  4. Factory Pattern implements Inversion by adding an abstraction layer as a central place for creating objects. If we try to look at other patterns it uses Inversion Creation patterns to abstract and handle dependencies.
IoC Container
So what are these Castle Windsor, Unity, Structure Map, and Ninject. Well, they are Dependency Resolvers or IoC Containers. Their responsibilities is to handle dependencies for us. Most especially when dependencies grow in numbers.

You can build your own IoC Containers just like the Factory Pattern but these APIs are handy and make the job easier for you.

I hope I was able to share knowledge and Thank you for your time.