Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto článku vytvoříte konzolovou aplikaci .NET, která ručně vytvoří ServiceCollection a k tomu odpovídající ServiceProvider. Naučíte se registrovat služby a řešit je pomocí injektáže závislostí (DI). Tento článek používá balíček NuGet Microsoft.Extensions.DependencyInjection k předvedení základů DI v .NET.
Poznámka:
Tento článek nevyužívá funkce obecného hostitele . Podrobnější průvodce najdete v tématu Použití injektáže závislostí v .NET.
Začínáme
Začněte vytvořením nové konzolové aplikace .NET s názvem DI.Basics. Na některé z nejběžnějších přístupů k vytvoření projektu konzoly se odkazuje v následujícím seznamu:
- Visual Studio: Nabídka Soubor > Nový > Projekt
- Visual Studio Code a rozšíření C# Dev Kit: možnost nabídky Průzkumník řešení.
-
.NET CLI:
dotnet new consolepříkaz v terminálu.
Do souboru projektu je potřeba přidat odkaz na balíček Microsoft.Extensions.DependencyInjection . Bez ohledu na přístup se ujistěte, že se projekt podobá následujícímu kódu XML souboru DI.Basics.csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
</ItemGroup>
</Project>
Základy injektování závislostí
Injektáž závislostí je vzor návrhu, který umožňuje odebrat pevně zakódované závislosti a zajistit, aby byla vaše aplikace lépe udržovatelná a testovatelná. DI je technika pro dosažení inverze řízení (IoC) mezi třídami a jejich závislostmi.
Abstrakce DI v .NET jsou definovány v balíčku NuGet Microsoft.Extensions.DependencyInjection.Abstractions:
- IServiceCollection: Definuje smlouvu pro kolekci popisovačů služeb.
- IServiceProvider: Definuje mechanismus pro načtení objektu služby.
- ServiceDescriptor: Popisuje službu s jejím typem služby, implementací a životností.
V .NET se di spravuje přidáním služeb a jejich konfigurací v objektu IServiceCollection. Po registraci IServiceProvider služeb je instance vytvořena voláním BuildServiceProvider metody. Funguje IServiceProvider jako kontejner všech registrovaných služeb a slouží k řešení služeb.
Vytvoření ukázkových služeb
Ne všechny služby se vytvářejí stejně. Některé služby vyžadují novou instanci pokaždé, když je kontejner služby získává (dočasná), zatímco jiné by měly být sdíleny v rámci požadavků (omezené na požadavky) nebo po celou dobu životnosti aplikace (singleton). Další informace o životnostech služeb najdete v tématu Životnost služby.
Podobně některé služby zpřístupňují pouze konkrétní typ, zatímco jiné jsou vyjádřeny jako kontrakt mezi rozhraním a typem implementace. Vytvoříte několik variant služeb, které vám pomůžou tyto koncepty předvést.
Vytvořte nový soubor C# s názvem IConsole.cs a přidejte následující kód:
public interface IConsole
{
void WriteLine(string message);
}
Tento soubor definuje IConsole rozhraní, které zveřejňuje jednu metodu , WriteLine. Dále vytvořte nový soubor C# s názvem DefaultConsole.cs a přidejte následující kód:
internal sealed class DefaultConsole : IConsole
{
public bool IsEnabled { get; set; } = true;
void IConsole.WriteLine(string message)
{
if (IsEnabled is false)
{
return;
}
Console.WriteLine(message);
}
}
Předchozí kód představuje výchozí implementaci IConsole rozhraní. Metoda WriteLine podmíněně zapisuje do konzoly na základě vlastnosti IsEnabled.
Návod
Pojmenování implementace je volba, na které by se měl váš vývojový tým shodnout. Předpona Default je běžnou konvencí označující výchozí implementaci rozhraní, ale nevyžaduje se.
Dále vytvořte soubor IGreetingService.cs a přidejte následující kód jazyka C#:
public interface IGreetingService
{
string Greet(string name);
}
Pak přidejte nový soubor C# s názvem DefaultGreetingService.cs a přidejte následující kód:
internal sealed class DefaultGreetingService(
IConsole console) : IGreetingService
{
public string Greet(string name)
{
var greeting = $"Hello, {name}!";
console.WriteLine(greeting);
return greeting;
}
}
Předchozí kód představuje výchozí implementaci IGreetingService rozhraní. Implementace služby vyžaduje IConsole jako primární parametr konstruktoru. Metoda Greet:
- Vytvoří
greetingpodle danéhoname. - Volá metodu
WriteLinena instanciIConsole. - Vrátí
greetingvolajícímu.
Poslední službou , která se má vytvořit, je soubor FarewellService.cs a před pokračováním přidejte následující kód jazyka C#:
public class FarewellService(IConsole console)
{
public string SayGoodbye(string name)
{
var farewell = $"Goodbye, {name}!";
console.WriteLine(farewell);
return farewell;
}
}
Představuje FarewellService konkrétní typ, nikoli rozhraní. Měla by být deklarována tak public , aby byla přístupná uživatelům. Na rozdíl od jiných typů implementace služby, které byly deklarovány jako internal a sealed, tento kód ukazuje, že ne všechny služby musí být rozhraní. Ukazuje také, že implementace služeb mohou bránit sealed dědičnosti a internal omezit přístup k sestavení.
Aktualizujte Program třídu
Otevřete soubor Program.cs a nahraďte stávající kód následujícím kódem jazyka C#:
using Microsoft.Extensions.DependencyInjection;
// 1. Create the service collection.
var services = new ServiceCollection();
// 2. Register (add and configure) the services.
services.AddSingleton<IConsole>(
implementationFactory: static _ => new DefaultConsole
{
IsEnabled = true
});
services.AddSingleton<IGreetingService, DefaultGreetingService>();
services.AddSingleton<FarewellService>();
// 3. Build the service provider from the service collection.
var serviceProvider = services.BuildServiceProvider();
// 4. Resolve the services that you need.
var greetingService = serviceProvider.GetRequiredService<IGreetingService>();
var farewellService = serviceProvider.GetRequiredService<FarewellService>();
// 5. Use the services
var greeting = greetingService.Greet("David");
var farewell = farewellService.SayGoodbye("David");
Předchozí aktualizovaný kód ukazuje postupy:
- Vytvořte novou
ServiceCollectioninstanci. - Registrace a konfigurace služeb v
ServiceCollection.-
IConsolepomocí přetížení implementační továrny vrátí typDefaultConsolesIsEnablednastaveným natrue. -
IGreetingServiceje přidán s odpovídajícím typem implementaceDefaultGreetingService. - Je
FarewellServicepřidán jako konkrétní typ.
-
- Sestavte
ServiceProviderzServiceCollection. - Řešení problémů
IGreetingServiceaFarewellServiceslužeb - Pomocí vyřešených služeb pozdravte a rozlučte se s osobou jménem
David.
Pokud aktualizujete IsEnabled vlastnost DefaultConsole na false, Greet a SayGoodbye metody vynechají zapsání výsledných zpráv do konzole. Taková změna pomůže ukázat, že je služba IConsolevložená do služeb IGreetingService a FarewellService jako závislost, která ovlivňuje chování aplikace.
Všechny tyto služby jsou registrovány jako singletony, i když pro tuto ukázku by fungovaly stejně, pokud by byly registrovány jako přechodné nebo jako vymezené služby.
Důležité
V tomto nepochybovaném příkladu nezáleží na životnosti služby, ale v reálné aplikaci byste měli pečlivě zvážit životnost každé služby.
Spuštění ukázkové aplikace
Ukázkovou aplikaci spustíte stisknutím klávesy F5 v sadě Visual Studio, editoru Visual Studio Code nebo spuštěním dotnet run příkazu v terminálu. Po dokončení aplikace by se měl zobrazit následující výstup:
Hello, David!
Goodbye, David!
Popisovače služeb
Nejčastěji používaná rozhraní API pro přidávání služeb do ServiceCollection jsou obecné rozšiřující metody s pojmenovanou dobou trvání, jako například:
AddSingleton<TService>AddTransient<TService>AddScoped<TService>
Tyto metody jsou praktické metody, které vytvářejí instanci ServiceDescriptor a přidávají ji do ServiceCollection. Jedná se ServiceDescriptor o jednoduchou třídu, která popisuje službu s jejím typem služby, typem implementace a životností. Může také popsat implementační továrny a instance.
Pro každou službu, kterou jste zaregistrovali v nástroji ServiceCollection, můžete místo toho použít metodu Add k volání instance ServiceDescriptor přímo. Zvažte následující příklady:
services.Add(ServiceDescriptor.Describe(
serviceType: typeof(IConsole),
implementationFactory: static _ => new DefaultConsole
{
IsEnabled = true
},
lifetime: ServiceLifetime.Singleton));
Předchozí kód odpovídá tomu, jak byla služba IConsole zaregistrována v ServiceCollection. Metoda Add se používá k přidání ServiceDescriptor instance, která popisuje IConsole službu. Statická metoda ServiceDescriptor.Describe deleguje na různé ServiceDescriptor konstruktory. Vezměte v úvahu ekvivalentní kód pro IGreetingService službu:
services.Add(ServiceDescriptor.Describe(
serviceType: typeof(IGreetingService),
implementationType: typeof(DefaultGreetingService),
lifetime: ServiceLifetime.Singleton));
Předchozí kód popisuje IGreetingService službu s jejím typem služby, typem implementace a životností. Nakonec zvažte ekvivalentní kód pro FarewellService službu:
services.Add(ServiceDescriptor.Describe(
serviceType: typeof(FarewellService),
implementationType: typeof(FarewellService),
lifetime: ServiceLifetime.Singleton));
Předchozí kód popisuje konkrétní FarewellService typ jako typ služby i implementace. Služba je zaregistrovaná jako jednoúčelová služba.