SOLID Principles
Dependency Injection

To achieve dependency inversion in a practical way, you can use dependency injection. Here's how you can apply it using a dependency injection container in a .NET application:


// Define the interfaces
public interface INotificationService
{
    void Notify(string to, string message);
}

// Implement the services
public class EmailService : INotificationService
{
    public void Notify(string to, string message)
    {
        // Send email logic
    }
}

// Implement the UserService
public class UserService
{
    private readonly INotificationService _notificationService;

    public UserService(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }

    public void RegisterUser(string email, string password)
    {
        // User registration logic
        _notificationService.Notify(email, "Welcome!");
    }
}

// Configure the DI container
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient();
        services.AddTransient();
    }
}

// In the application code
public class Program
{
    public static void Main(string[] args)
    {
        var serviceProvider = new ServiceCollection()
            .AddTransient()
            .AddTransient()
            .BuildServiceProvider();

        var userService = serviceProvider.GetService();
        userService.RegisterUser("user@example.com", "password123");
    }
}

In this example, the INotificationService is injected into the UserService using a dependency injection container, promoting loose coupling and adherence to the Dependency Inversion Principle.

Conclusion

The Dependency Inversion Principle encourages the use of abstractions to decouple high-level and low-level modules. By relying on interfaces or abstract classes, you can create flexible, maintainable, and testable code. Dependency injection is a practical way to implement DIP in real-world applications, ensuring that your high-level modules remain independent of low-level module implementations.