design

Introduction to Dependency Injection in .NET Core: The Right Way!

April 6, 2025

Dependency Injection (DI) is built into .NET Core's DNA—let's demystify this powerful pattern that makes your code more testable, maintainable, and flexible!


🔍 What is Dependency Injection?

A design pattern where:

✔ Objects receive their dependencies (services) from outside

✔ No hard-coded dependencies ("new" keyword avoided)

✔ Loose coupling between components


🏗 .NET Core DI System Overview


1. Service Registration (Startup.cs)

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService, MyService>(); // New instance every time
    services.AddScoped<IDatabaseService, DatabaseService>(); // Per request
    services.AddSingleton<ILogger, FileLogger>(); // Single instance forever
}


2. Service Consumption

public class MyController : Controller
{
    private readonly IMyService _service;
    
    // Constructor injection (preferred)
    public MyController(IMyService service)
    {
        _service = service;
    }
}


🎯 Lifetime Options Explained

LifetimeUsageExampleTransientNew instance every requestLightweight stateless servicesScopedSame instance per HTTP requestDbContext in EF CoreSingletonSingle instance foreverConfiguration, Logging💡 Pro Tips

✅ Always prefer constructor injection (clearly shows dependencies)

✅ Use interfaces for easy mocking in tests

✅ Avoid Service Locator pattern (anti-pattern!)


// ❌ Avoid this!
var service = HttpContext.RequestServices.GetService<IMyService>();


🚀 Practical Example: Email Service

1. Define Interface


public interface IEmailService
{
    Task SendEmail(string to, string body);
}


2. Implement Service

public class SmtpEmailService : IEmailService
{
    public Task SendEmail(string to, string body)
    {
        // Actual email sending logic
    }
}


3. Register & Use

// Registration
services.AddTransient<IEmailService, SmtpEmailService>();

// Usage in controller
public class UserController : Controller
{
    private readonly IEmailService _emailService;
    
    public UserController(IEmailService emailService)
    {
        _emailService = emailService;
    }
}


🔥 Why DI Rocks in .NET Core

✔ Easy unit testing (mock dependencies)

✔ Decoupled architecture

✔ Built-in container (no 3rd-party libs needed)

✔ Lifetime management handled automatically

Next Steps: Try replacing a direct dependency in your project with DI today!


#DotNetCore #DependencyInjection #CleanCode #CSharp #BestPractices

5 + 1 =