Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Dependency Injection

Introduction to Dependency Injection

Dependency Injection (DI) is a design pattern used to implement Inversion of Control (IoC) between classes and their dependencies. It allows for better modularity and testability by injecting dependencies rather than creating them within the classes.

Why Use Dependency Injection?

  • Decoupling: Reduces the dependency of one class on another.
  • Testability: Makes it easier to test individual components.
  • Maintainability: Simplifies code maintenance and updates.

Setting Up Dependency Injection in .NET

In .NET, DI is supported out of the box and can be configured in the Startup.cs file.

Step 1: Define Interfaces and Implementations

Example: Defining Interfaces and Implementations


public interface IMessageService {
    void SendMessage(string message);
}

public class EmailService : IMessageService {
    public void SendMessage(string message) {
        Console.WriteLine($"Email sent: {message}");
    }
}

public class SmsService : IMessageService {
    public void SendMessage(string message) {
        Console.WriteLine($"SMS sent: {message}");
    }
}
    

Step 2: Configure Services in Startup.cs

Example: Configuring Services in Startup.cs


public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        services.AddTransient();
        // services.AddTransient(); // Uncomment to use SmsService
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        // Middleware configuration
    }
}
    

Step 3: Inject Dependencies in Controllers

Example: Injecting Dependencies in Controllers


public class HomeController : Controller {
    private readonly IMessageService _messageService;

    public HomeController(IMessageService messageService) {
        _messageService = messageService;
    }

    public IActionResult Index() {
        _messageService.SendMessage("Welcome to Dependency Injection in .NET!");
        return View();
    }
}
    

Lifetime of Services

In .NET DI, services can have different lifetimes:

  • Transient: Created each time they are requested.
  • Scoped: Created once per request.
  • Singleton: Created the first time they are requested and used for the lifetime of the application.

Example: Configuring Service Lifetimes

Example: Configuring Service Lifetimes


public void ConfigureServices(IServiceCollection services) {
    services.AddTransient(); // Transient
    services.AddScoped(); // Scoped
    services.AddSingleton(); // Singleton
}
    

Advanced Dependency Injection

For more complex scenarios, you can use advanced DI techniques such as:

  • Named Instances: Using named services for different implementations.
  • Factory Methods: Using factories to create service instances.
  • Decorator Pattern: Adding behavior to services.

Example: Using Factory Methods

Example: Using Factory Methods


public void ConfigureServices(IServiceCollection services) {
    services.AddTransient(provider => {
        var useEmail = bool.Parse(Configuration["UseEmail"]);
        if (useEmail) {
            return new EmailService();
        } else {
            return new SmsService();
        }
    });
}
    

Conclusion

Dependency Injection is a powerful pattern that enhances the modularity, testability, and maintainability of your applications. By understanding and implementing DI in .NET, you can create more flexible and robust applications.