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:
MainProgramis the starting participant that creates an instance ofTaskProcessor.TaskProcessoris activated, indicating that it is in the process of being executed.TaskProcessorthen injects an instance ofITaskServiceinto itself, provided byMainProgram. In this example, it could be an instance ofTaskService.TaskProcessorcalls thePerformTask()method on the injectedITaskService.TaskServiceis activated to execute thePerformTask()method.TaskServicereturns the result toTaskProcessor.- Finally,
TaskProcessorreturns 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:
ITaskServiceis an interface representing a service with aPerformTask()method.TaskServiceis a concrete implementation ofITaskService.TaskProcessoris a class that depends onITaskService. Instead of creating an instance ofTaskServicewithinTaskProcessor, it receives an instance ofITaskServicethrough constructor injection.- In the
Main()method, an instance ofTaskServiceis 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