DevIQ
Inversion of Control
Inversion of Control
Inversion of Control (IoC or IOC) describes a system that follows the Hollywood Principle. That is, flow of control within the application is not controlled by the application itself, but rather by the underlying framework. Typically in such an architecture, the application is written such that it ties into the application framework by handling framework events or plugging in to framework extension points.
An IoC Container, also known as a Dependency Inversion (DI) container, is a specialized factory used to facilitate dependency injection.
Code Example for IoC
For this concept, let's look at a hypothetical task processor and task service. The task processor (TaskProcessor
) will get called in the main application to perform a task. Then, it will get an injected implementation of the interface, and it will call the PerformTask()
on the injected implementation. The task processor doesn't have a specific implementation in its code - it just knows that it needs an implementation that fulfills a specific interface. The main application is responsible for injecting in the specific implementation.
The Flow of IoC
Let's look at this situation with a sequence diagram.
In this sequence diagram:
MainProgram
is the starting participant that creates an instance ofTaskProcessor
.TaskProcessor
is activated, indicating that it is in the process of being executed.TaskProcessor
then injects an instance ofITaskService
into itself, provided byMainProgram
. In this example, it could be an instance ofTaskService
.TaskProcessor
calls thePerformTask()
method on the injectedITaskService
.TaskService
is activated to execute thePerformTask()
method.TaskService
returns the result toTaskProcessor
.- Finally,
TaskProcessor
returns the result toMainProgram
, and it is deactivated.
This is the sequence diagram:
Code Sample of IoC
This is a sample of what inversion of control could look like using C#.
In this example:
ITaskService
is an interface representing a service with aPerformTask()
method.TaskService
is a concrete implementation ofITaskService
.TaskProcessor
is a class that depends onITaskService
. Instead of creating an instance ofTaskService
withinTaskProcessor
, it receives an instance ofITaskService
through constructor injection.- In the
Main()
method, an instance ofTaskService
is created and passed to the constructor of TaskProcessor. The control flow is inverted because TaskProcessor doesn't create or manage its dependencies; they are injected from the outside.
// Service interfacepublic interface ITaskService{ string PerformTask();}
// Concrete implementation of the servicepublic class TaskService : ITaskService{ public string PerformTask() { // Task logic here return "Task completed"; }}
// Class that depends on ITaskServicepublic class TaskProcessor{ private readonly ITaskService taskService;
// Constructor injection of the dependency public TaskProcessor(ITaskService taskService) { this.taskService = taskService; }
public string ProcessTask() { // Using the injected dependency return taskService.PerformTask(); }}
// Main programclass Program{ static void Main() { // Setting up the IoC container (dependency injection container) // In a real-world scenario, you might use a more robust IoC container like Autofac, Unity, etc. ITaskService taskService = new TaskService(); TaskProcessor taskProcessor = new TaskProcessor(taskService);
// Using the TaskProcessor without worrying about creating its dependencies string result = taskProcessor.ProcessTask(); Console.WriteLine(result); }}
See Also
References
Inversion of Control (Wikipedia)
Comparing Major C# IOC Containers
Edit this page on GitHub