C# Academy · Lektion

Grunderna i DI-containrar

Förstå inversion of control, tjänsteregistrering och hur .NET DI-containern löser beroenden.

Lektion 1 av 413 steg

Grunderna i DI-containrar är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för C# Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i C# Academy innehåller totalt 4 lektioner.

Vad är dependency injection

Dependency injection (DI) är ett designmönster där en klass får sina beroenden från en extern källa i stället för att skapa dem själv.

I stället för att skriva var repo = new UserRepository(); i en klass deklarerar klassen vad den behöver, och DI-containern tillhandahåller det.

Inversion of Control

DI är en konkret implementering av principen Inversion of Control (IoC): kontrollen över att skapa beroenden flyttas från den beroende klassen till en extern container.

Det gör klasser enklare att testa och byta ut.

Konfigurera .NET DI-containern

I en .NET-app konfigureras DI-containern via IServiceCollection i Program.cs. Tjänster registreras och löses sedan av körningen.

var builder = WebApplication.CreateBuilder(args);

// Register services
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<UserService>();

var app = builder.Build();
app.Run();

Definiera ett gränssnitt och en implementation

DI fungerar bäst när du programmerar mot gränssnitt. Definiera ett gränssnitt för tjänstekontraktet och en konkret klass som implementerar det.

public interface IUserRepository
{
    User? GetById(int id);
}

public class UserRepository : IUserRepository
{
    public User? GetById(int id)
    {
        // fetch from database
        return new User { Id = id, Name = "Alice" };
    }
}

Lösa upp tjänster via konstruktorn

Containern injicerar automatiskt registrerade tjänster i konstruktorer. Klassen behöver bara deklarera vilket gränssnitt den behöver – inget new-nyckelord krävs.

public class UserService
{
    private readonly IUserRepository _repo;

    public UserService(IUserRepository repo)
    {
        _repo = repo;
    }

    public User? FindUser(int id) => _repo.GetById(id);
}

Registrera flera tjänster

Du kan registrera så många tjänster som behövs. Vanliga tilläggsmetoder är AddTransient, AddScoped och AddSingleton – var och en definierar en annan livslängd.

builder.Services.AddSingleton<IConfig, AppConfig>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddScoped<UserService>();

Använda IServiceProvider direkt

I sällsynta fall behöver du lösa upp tjänster imperativt. Med IServiceProvider kan du anropa GetRequiredService<T>() för att lösa upp en tjänst, men föredra konstruktorinjektion i de flesta situationer.

// Anti-pattern (service locator) — use sparingly
public class ManualResolver
{
    private readonly IServiceProvider _sp;

    public ManualResolver(IServiceProvider sp) => _sp = sp;

    public void DoWork()
    {
        var svc = _sp.GetRequiredService<UserService>();
        svc.FindUser(1);
    }
}

Registrera öppna generiska typer

.NET DI har stöd för registrering av öppna generiska typer. Du kan registrera IRepository<> en gång, så löses det upp till Repository<T> för alla entitetstyper.

builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

// Resolves as:
// IRepository<User> -> Repository<User>
// IRepository<Order> -> Repository<Order>

Validering vid programstart

Med ValidateOnStart() eller ValidateScopes = true kan containern upptäcka felaktigt konfigurerade registreringar (till exempel att en Scoped-tjänst hålls kvar av en Singleton) när programmet startar i stället för vid körning.

builder.Services.AddScoped<IMyService, MyService>();

// Detect scope violations at startup
builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;
    options.ValidateOnBuild = true;
});

Dekorera tjänster

Du kan omsluta en tjänst med en dekoratör utan att ändra den ursprungliga klassen. Registrera den inre tjänsten först och registrera sedan dekoratören som omsluter den.

builder.Services.AddScoped<IUserRepository, UserRepository>();

// Decorator pattern
builder.Services.Decorate<IUserRepository, CachedUserRepository>();
// Requires Scrutor NuGet package

I praktiken: Minimal API med DI

I ett Minimal API injiceras tjänster direkt i parametrarna till route-hanterare. Containern löser automatiskt upp dem.

app.MapGet("/users/{id}", (int id, UserService svc) =>
{
    var user = svc.FindUser(id);
    return user is null ? Results.NotFound() : Results.Ok(user);
});

Snabb kontroll

Vilken metod bör du föredra för att hämta beroenden i de flesta klasser?

Sammanfattning: Grunderna i DI-containern

Viktiga lärdomar:

  • DI vänder på skapandet av beroenden: containern skapar objekten, inte klassen själv
  • Registrera tjänster med AddTransient / AddScoped / AddSingleton
  • Konstruktorinjektion är standardmetoden och den rekommenderade metoden
  • Öppna generiska typer, dekoratörer och ValidateOnBuild är kraftfulla avancerade funktioner
Gratis att börja

Lär dig C# med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
93
Lektioner
346

Vanliga frågor

Är lektionen ”Grunderna i DI-containrar” gratis?

Ja – hela texten till ”Grunderna i DI-containrar” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i C# Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i C# Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Grunderna i DI-containrar”?

Förstå inversion of control, tjänsteregistrering och hur .NET DI-containern löser beroenden. Ni övar på C# Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig C# Academy?

Du behöver inga förkunskaper. Utbildningen i C# Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Grunderna i DI-containrar”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här C# Academy-lektionen?

Ja. Varje C# Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Grunderna i DI-containrar
  2. Tjänstelivslängder: Transient, Scoped, Singleton
  3. Konstruktorinjektion och gränssnitt
  4. Factory- och Options-mönster
← Tillbaka till C# Academy