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.
.NET podporuje model návrhu softwaru injektáž závislostí (DI), což je technika pro dosažení inverze řízení (IoC) mezi třídami a jejich závislostmi. Injektáž závislostí v .NET je integrovaná součást architektury spolu s konfigurací, protokolováním a vzorem možností.
Závislost je objekt, na který závisí jiný objekt. Prozkoumejte následující MessageWriter třídu pomocí Write metody, na které závisí jiné třídy:
public class MessageWriter
{
public void Write(string message)
{
Console.WriteLine($"MessageWriter.Write(message: \"{message}\")");
}
}
Třída může vytvořit instanci MessageWriter třídy pro použití její Write metody. V následujícím příkladu MessageWriter je třída závislostí Worker třídy:
public class Worker : BackgroundService
{
private readonly MessageWriter _messageWriter = new();
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
await Task.Delay(1_000, stoppingToken);
}
}
}
Třída vytvoří a přímo závisí na MessageWriter třídě. Pevně zakódované závislosti, například v předchozím příkladu, jsou problematické a měly by se vyhnout z následujících důvodů:
- Chcete-li nahradit
MessageWriterjinou implementací, je nutné upravitWorkertřídu. - Pokud
MessageWriterobsahuje závislosti,Workertřída je také musí nakonfigurovat. Ve velkém projektu s více třídami v závislosti naMessageWritertom se konfigurační kód rozdělí v aplikaci. - Tato implementace je obtížná pro testování jednotek. Aplikace by měla používat napodobení nebo třídu zástupných procedur
MessageWriter, která s tímto přístupem není možná.
Injektáž závislostí řeší následující problémy prostřednictvím:
- Použití rozhraní nebo základní třídy k abstrakci implementace závislostí.
- Registrace závislosti v kontejneru služby .NET poskytuje integrovaný kontejner služby . IServiceProvider Služby se obvykle registrují v start-upu aplikace a připojí se k sadě IServiceCollection. Po přidání všech služeb použijte BuildServiceProvider k vytvoření kontejneru služby.
- Injektáž služby do konstruktoru třídy, ve které se používá. Architektura přebírá odpovědnost za vytvoření instance závislosti a její likvidaci, když už ji nepotřebujete.
IMessageWriter Například rozhraní definuje metoduWrite:
namespace DependencyInjection.Example;
public interface IMessageWriter
{
void Write(string message);
}
Toto rozhraní je implementováno konkrétním typem: MessageWriter
namespace DependencyInjection.Example;
public class MessageWriter : IMessageWriter
{
public void Write(string message)
{
Console.WriteLine($"MessageWriter.Write(message: \"{message}\")");
}
}
Vzorový kód zaregistruje IMessageWriter službu s konkrétním typem MessageWriter. Metoda AddSingleton zaregistruje službu s jednou životností, životností aplikace.
Životnosti služeb jsou popsány dále v tomto článku.
using DependencyInjection.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
builder.Services.AddSingleton<IMessageWriter, MessageWriter>();
using IHost host = builder.Build();
host.Run();
V předchozím kódu ukázková aplikace:
Vytvoří instanci tvůrce hostitelských aplikací.
Nakonfiguruje služby registrací:
- Jako
Workerhostovaná služba. Další informace naleznete v tématu Pracovní služby v .NET. - Rozhraní
IMessageWriterjako jednoúčelová služba s odpovídající implementacíMessageWritertřídy.
- Jako
Vytvoří hostitele a spustí ho.
Hostitel obsahuje poskytovatele služby injektáže závislostí. Obsahuje také všechny ostatní relevantní služby potřebné k automatickému vytvoření instance Worker a poskytnutí odpovídající IMessageWriter implementace jako argumentu.
namespace DependencyInjection.Example;
public sealed class Worker(IMessageWriter messageWriter) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
await Task.Delay(1_000, stoppingToken);
}
}
}
Pomocí vzoru DI služba pracovního procesu:
- Nepoužívá konkrétní typ
MessageWriter, pouzeIMessageWriterrozhraní, které implementuje. To usnadňuje změnu implementace, kterou worker service používá, aniž by bylo potřeba měnit samotnou worker service. - Nevytvoří instanci
MessageWriter. Kontejner DI vytvoří instanci.
Implementaci rozhraní je možné vylepšit pomocí integrovaného IMessageWriter rozhraní API pro protokolování:
namespace DependencyInjection.Example;
public class LoggingMessageWriter(
ILogger<LoggingMessageWriter> logger) : IMessageWriter
{
public void Write(string message) =>
logger.LogInformation("Info: {Msg}", message);
}
Aktualizovaná AddSingleton metoda zaregistruje novou IMessageWriter implementaci:
builder.Services.AddSingleton<IMessageWriter, LoggingMessageWriter>();
Typ HostApplicationBuilder (builder) je součástí Microsoft.Extensions.Hosting balíčku NuGet.
LoggingMessageWriter závisí na tom , který ILogger<TCategoryName>požaduje v konstruktoru.
ILogger<TCategoryName>je služba poskytovaná architekturou.
Není neobvyklé používat injektáž závislostí zřetězeným způsobem. Každá požadovaná závislost zase vyžaduje vlastní závislosti. Kontejner vyřeší závislosti v grafu a vrátí plně vyřešenou službu. Souhrnná sada závislostí, které je nutné vyřešit, se obvykle označuje jako strom závislostí, graf závislostí nebo objektový graf.
Kontejner se ILogger<TCategoryName> vyřeší tím, že využívá (obecné) otevřené typy a eliminuje potřebu registrovat každý (obecný) vytvořený typ.
Pomocí terminologie injektáže závislostí služba:
- Je obvykle objekt, který poskytuje službu jiným objektům, jako
IMessageWriterje služba. - Nesouvisí s webovou službou, i když služba může používat webovou službu.
Architektura poskytuje robustní systém protokolování. Implementace IMessageWriter uvedené v předchozích příkladech demonstrují základní DI, nikoli protokolování. Většina aplikací by neměla zapisovat protokolovací nástroje. Následující kód ukazuje použití výchozího protokolování, které vyžaduje Worker registraci pouze jako hostované služby AddHostedService:
public sealed class Worker(ILogger<Worker> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1_000, stoppingToken);
}
}
}
Pomocí předchozího kódu není nutné aktualizovat Program.cs, protože architektura poskytuje protokolování.
Pravidla zjišťování více konstruktorů
Pokud typ definuje více než jeden konstruktor, poskytovatel služeb má logiku pro určení konstruktoru, který se má použít. Konstruktor s nejvíce parametry, ve kterých jsou typy di-přeložitelné, je vybrán. Představte si následující ukázkovou službu jazyka C#:
public class ExampleService
{
public ExampleService()
{
}
public ExampleService(ILogger<ExampleService> logger)
{
// omitted for brevity
}
public ExampleService(FooService fooService, BarService barService)
{
// omitted for brevity
}
}
V předchozím kódu předpokládejme, že bylo přidáno protokolování, které lze vyřešit od poskytovatele služeb, ale typy FooService a BarService nejsou. Konstruktor s parametrem ILogger<ExampleService> vyřeší instanci ExampleService. I když existuje konstruktor, který definuje více parametrů, FooService a BarService typy nelze vyřešit DI.
Pokud při zjišťování konstruktorů existuje nejednoznačnost, vyvolá se výjimka. Představte si následující ukázkovou službu jazyka C#:
public class ExampleService
{
public ExampleService()
{
}
public ExampleService(ILogger<ExampleService> logger)
{
// omitted for brevity
}
public ExampleService(IOptions<ExampleOptions> options)
{
// omitted for brevity
}
}
Upozorňující
Kód ExampleService s nejednoznačnými typovými parametry, které mohou být vyřešeny DI, vyvolá výjimku.
Nedělejte to – účelem je ukázat, co znamená "nejednoznačné DI-resolvovatelné typy".
V předchozím příkladu existují tři konstruktory. První konstruktor je bez parametrů a nevyžaduje žádné služby od poskytovatele služeb. Předpokládejme, že do kontejneru DI byly přidány protokolování i možnosti a že se jedná o služby, které lze přeložit. Když se kontejner DI pokusí vyřešit typ ExampleService, vyvolá výjimku, protože dva konstruktory jsou nejednoznačné.
Vyhněte se nejednoznačnosti definováním konstruktoru, který místo toho přijímá oba typy překladu DI:
public class ExampleService
{
public ExampleService()
{
}
public ExampleService(
ILogger<ExampleService> logger,
IOptions<ExampleOptions> options)
{
// omitted for brevity
}
}
Registrace skupin služeb pomocí rozšiřujících metod
Rozšíření Microsoftu používají konvenci pro registraci skupiny souvisejících služeb. Konvence spočívá v použití jedné Add{GROUP_NAME} rozšiřující metody k registraci všech služeb vyžadovaných funkcí architektury. Například AddOptions metoda rozšíření zaregistruje všechny služby potřebné pro použití možností.
Služby poskytované architekturou
Při použití některého z dostupných vzorů hostitele nebo tvůrce aplikací se použijí výchozí hodnoty a rozhraní zaregistruje služby. Představte si některé z nejoblíbenějších vzorů pro hostitele a tvůrce aplikací:
- Host.CreateDefaultBuilder()
- Host.CreateApplicationBuilder()
- WebHost.CreateDefaultBuilder()
- WebApplication.CreateBuilder()
- WebAssemblyHostBuilder.CreateDefault
- MauiApp.CreateBuilder
Po vytvoření builderu z některého z těchto rozhraní API IServiceCollection má služby definované frameworkem, v závislosti na tom, jak jste hostitele nakonfigurovali. Pro aplikace založené na šablonách .NET by architektura mohla zaregistrovat stovky služeb.
Následující tabulka uvádí malou ukázku těchto služeb registrovaných architekturou:
Životnost služeb
Služby je možné zaregistrovat v jedné z následujících životností:
Následující části popisují jednotlivé předchozí životnosti. Zvolte odpovídající dobu života pro každou zaregistrovanou službu.
Přechodná
Přechodné služby životnosti se vytvářejí při každém vyžádání z kontejneru služby. Chcete-li zaregistrovat službu jako přechodná, zavolejte AddTransient.
Vaplikacích Vzhledem k tomu, že se služby řeší a vytvářejí pokaždé, když se tato doba životnosti účtují a konstruují na jednotlivé požadavky. Další informace najdete v tématu Pokyny pro injektáž závislostí: Pokyny pro IDisposable pro přechodné a sdílené instance.
Rozsahem
U webových aplikací doba života s vymezeným oborem značí, že se služby vytvoří jednou podle požadavku klienta (připojení). Zaregistrujte služby s vymezeným oborem pomocí AddScoped.
V aplikacích, které zpracovávají požadavky, se na konci požadavku zlikvidují omezené služby.
Poznámka:
Při použití Entity Framework Core AddDbContext metoda rozšíření ve výchozím nastavení registruje DbContext typy s vymezenou životností.
Vymezená služba by se měla vždy používat v rámci oboru – buď implicitní obor (například rozsah ASP.NET Core podle požadavku), nebo explicitní obor vytvořený pomocí IServiceScopeFactory.CreateScope().
Nepoužívejte službu s vymezeným oborem přímo v singletonu pomocí injektáže konstruktoru nebo jejím vyžádáním v rámci singletonu.IServiceProvider Tím dojde k tomu, že se vymezená služba chová jako singleton, což může při zpracování následných požadavků vést k nesprávnému stavu.
Pokud vytváříte a používáte explicitní obor pomocí IServiceScopeFactory, je přijatelné řešit vymezenou službu v rámci singletonu.
Je také v pořádku:
- Vyřešte službu singleton z omezené nebo přechodné služby.
- Vyřešte vymezenou službu z jiné služby s vymezeným oborem nebo přechodnou službou.
Ve výchozím nastavení vyvolá řešení služby z jiné služby s delší životností výjimku. Další informace najdete v tématu Ověření oboru.
Unikát
Služby s jednou životností se vytvářejí buď:
- Při prvním vyžádání.
- Vývojář při poskytování instance implementace přímo do kontejneru. Tento přístup je zřídka nutný.
Každý další požadavek implementace služby z kontejneru injektáže závislostí používá stejnou instanci. Pokud aplikace vyžaduje jednoúčelové chování, povolte kontejneru služby správu životnosti služby. Neimplementujte vzor návrhu singleton a poskytněte kód pro odstranění singletonu. Služby by nikdy neměly být uvolněny kódem, který službu přeložil z kontejneru. Pokud je typ nebo továrna registrována jako singleton, kontejner automaticky odstraní jednoton.
Zaregistrujte jednoúčelové služby pomocí AddSingleton. Jednoúčelové služby musí být bezpečné pro přístup z více vláken a často se používají v bezstavových službách.
V aplikacích, které zpracovávají požadavky, se vyřadí jednoúčelové služby, když ServiceProvider se vyřadí při vypnutí aplikace. Vzhledem k tomu, že paměť není uvolněna, dokud aplikace neukončí činnost, zvažte použití paměti pomocí singleton služby.
Metody registrace služby
Architektura poskytuje metody rozšíření registrace služeb, které jsou užitečné v konkrétních scénářích:
| metoda | Automatic (Automaticky) objekt likvidace |
Více implementace |
Předávání args |
|---|---|---|---|
Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>()Příklad: services.AddSingleton<IMyDep, MyDep>(); |
Ano | Ano | Ne |
Add{LIFETIME}<{SERVICE}>(sp => new {IMPLEMENTATION})Příklady: services.AddSingleton<IMyDep>(sp => new MyDep());services.AddSingleton<IMyDep>(sp => new MyDep(99)); |
Ano | Ano | Ano |
Add{LIFETIME}<{IMPLEMENTATION}>()Příklad: services.AddSingleton<MyDep>(); |
Ano | Ne | Ne |
AddSingleton<{SERVICE}>(new {IMPLEMENTATION})Příklady: services.AddSingleton<IMyDep>(new MyDep());services.AddSingleton<IMyDep>(new MyDep(99)); |
Ne | Ano | Ano |
AddSingleton(new {IMPLEMENTATION})Příklady: services.AddSingleton(new MyDep());services.AddSingleton(new MyDep(99)); |
Ne | Ne | Ano |
Další informace o odstranění typu naleznete v části Vyřazení služeb .
Registrace služby pouze s typem implementace je ekvivalentní registraci této služby se stejným typem implementace a služby. Představte si například následující kód:
services.AddSingleton<ExampleService>();
To je ekvivalentem registrace služby ve službě i implementaci stejných typů:
services.AddSingleton<ExampleService, ExampleService>();
Tato ekvivalence je důvod, proč není možné zaregistrovat více implementací služby pomocí metod, které nepoužívají explicitní typ služby. Tyto metody mohou zaregistrovat více instancí služby , ale všechny mají typ implementace stejný.
Libovolnou metodu registrace služby lze použít k registraci více instancí služby stejného typu služby. V následujícím příkladu AddSingleton se jako typ služby volá dvakrát IMessageWriter . Druhé volání, které AddSingleton přepíše předchozí, když je vyřešeno jako IMessageWriter a přidá do předchozího volání při vyřešení více služeb prostřednictvím IEnumerable<IMessageWriter>. Služby se zobrazují v pořadí, v jakém byly zaregistrovány při vyřešení prostřednictvím IEnumerable<{SERVICE}>.
using ConsoleDI.IEnumerableExample;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<IMessageWriter, ConsoleMessageWriter>();
builder.Services.AddSingleton<IMessageWriter, LoggingMessageWriter>();
builder.Services.AddSingleton<ExampleService>();
using IHost host = builder.Build();
_ = host.Services.GetService<ExampleService>();
await host.RunAsync();
Předchozí vzorový zdrojový kód registruje dvě implementace IMessageWriter.
using System.Diagnostics;
namespace ConsoleDI.IEnumerableExample;
public sealed class ExampleService
{
public ExampleService(
IMessageWriter messageWriter,
IEnumerable<IMessageWriter> messageWriters)
{
Trace.Assert(messageWriter is LoggingMessageWriter);
var dependencyArray = messageWriters.ToArray();
Trace.Assert(dependencyArray[0] is ConsoleMessageWriter);
Trace.Assert(dependencyArray[1] is LoggingMessageWriter);
}
}
Definuje ExampleService dva parametry konstruktoru, jeden IMessageWritera .IEnumerable<IMessageWriter> Jedinou IMessageWriter implementací je poslední registrace, zatímco IEnumerable<IMessageWriter> představuje všechny registrované implementace.
Architektura také poskytuje TryAdd{LIFETIME} rozšiřující metody, které zaregistrují službu pouze v případě, že ještě není zaregistrovaná implementace.
V následujícím příkladu volání AddSingleton registrů ConsoleMessageWriter jako implementace pro IMessageWriter. Volání TryAddSingleton nemá žádný účinek, protože IMessageWriter již má zaregistrovanou implementaci:
services.AddSingleton<IMessageWriter, ConsoleMessageWriter>();
services.TryAddSingleton<IMessageWriter, LoggingMessageWriter>();
Nemá TryAddSingleton žádný vliv, protože už byl přidán a pokus selže. Tento ExampleService výraz potvrzuje následující:
public class ExampleService
{
public ExampleService(
IMessageWriter messageWriter,
IEnumerable<IMessageWriter> messageWriters)
{
Trace.Assert(messageWriter is ConsoleMessageWriter);
Trace.Assert(messageWriters.Single() is ConsoleMessageWriter);
}
}
Další informace naleznete v tématu:
Metody TryAddEnumerable(ServiceDescriptor) registrují službu pouze v případě, že ještě neexistuje implementace stejného typu. Více služeb je vyřešeno prostřednictvím IEnumerable<{SERVICE}>. Při registraci služeb přidejte instanci, pokud ještě nebyl přidán jeden ze stejných typů. Autoři knihoven se používají TryAddEnumerable k tomu, aby se zabránilo registraci více kopií implementace v kontejneru.
V následujícím příkladu první volání TryAddEnumerable registruje MessageWriter jako implementace pro IMessageWriter1. Druhý hovor se zaregistruje MessageWriter pro IMessageWriter2. Třetí volání nemá žádný účinek, protože IMessageWriter1 již má zaregistrovanou implementaci MessageWriter:
public interface IMessageWriter1 { }
public interface IMessageWriter2 { }
public class MessageWriter : IMessageWriter1, IMessageWriter2
{
}
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMessageWriter1, MessageWriter>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMessageWriter2, MessageWriter>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMessageWriter1, MessageWriter>());
Registrace služby je nezávislá na objednávce s výjimkou registrace více implementací stejného typu.
IServiceCollection je kolekce ServiceDescriptor objektů. Následující příklad ukazuje, jak zaregistrovat službu vytvořením a přidáním ServiceDescriptor:
string secretKey = Configuration["SecretKey"];
var descriptor = new ServiceDescriptor(
typeof(IMessageWriter),
_ => new DefaultMessageWriter(secretKey),
ServiceLifetime.Transient);
services.Add(descriptor);
Integrované Add{LIFETIME} metody používají stejný přístup. Podívejte se například na zdrojový kód AddScoped.
Chování injektáže konstruktoru
Služby je možné vyřešit pomocí:
- IServiceProvider
-
ActivatorUtilities:
- Vytvoří objekty, které nejsou zaregistrované v kontejneru.
- Používá se s některými funkcemi architektury.
Konstruktory mohou přijímat argumenty, které nejsou poskytovány injektáží závislostí, ale argumenty musí přiřadit výchozí hodnoty.
Při vyvolávání služeb pomocí IServiceProvider nebo ActivatorUtilities vyžaduje injektáž konstruktoru veřejný konstruktor.
Při ActivatorUtilities rezolvování služeb injektování konstruktoru vyžaduje, aby existoval pouze jeden použitelný konstruktor. Přetížení konstruktoru jsou podporována, ale pouze jedno přetížení může existovat, jehož argumenty mohou být splněny injektáž závislostí.
Ověření oboru
Když se aplikace spustí v Development prostředí a zavolá createApplicationBuilder k sestavení hostitele, výchozí poskytovatel služeb provede kontroly, aby ověřil, že:
- Služby s vymezeným oborem se od poskytovatele kořenových služeb nepřeloží.
- Služby s vymezeným oborem se nevkážou do singletonů.
Po zavolání se vytvoří BuildServiceProvider poskytovatel kořenové služby. Životnost poskytovatele kořenových služeb odpovídá životnosti aplikace, když poskytovatel začne s aplikací a je uvolněn při vypnutí aplikace.
Omezené služby jsou uvolněny kontejnerem, který je vytvořil. Pokud se v kořenovém kontejneru vytvoří vymezená služba, životnost služby se efektivně zvýší na singleton, protože je odstraněna pouze kořenovým kontejnerem, když se aplikace vypne. Ověřování rozsahů služby tyto situace zachytí, když BuildServiceProvider je volána.
Scénáře oborů
Je IServiceScopeFactory vždy registrován jako singleton, ale IServiceProvider může se lišit v závislosti na životnosti obsahující třídy. Pokud například vyřešíte služby ze scope a některá z těchto služeb převezme IServiceProvider, jedná se o instance v rámci rozsahu.
Pokud chcete dosáhnout rozsahu služeb v rámci implementací IHostedService, jako je například BackgroundService, nepřidávejte závislosti služby prostřednictvím injektáže konstruktoru. Místo toho vložte IServiceScopeFactory, vytvořte obor a pak přeložte závislosti z oboru tak, aby používala odpovídající dobu životnosti služby.
namespace WorkerScope.Example;
public sealed class Worker(
ILogger<Worker> logger,
IServiceScopeFactory serviceScopeFactory)
: BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (IServiceScope scope = serviceScopeFactory.CreateScope())
{
try
{
logger.LogInformation(
"Starting scoped work, provider hash: {hash}.",
scope.ServiceProvider.GetHashCode());
var store = scope.ServiceProvider.GetRequiredService<IObjectStore>();
var next = await store.GetNextAsync();
logger.LogInformation("{next}", next);
var processor = scope.ServiceProvider.GetRequiredService<IObjectProcessor>();
await processor.ProcessAsync(next);
logger.LogInformation("Processing {name}.", next.Name);
var relay = scope.ServiceProvider.GetRequiredService<IObjectRelay>();
await relay.RelayAsync(next);
logger.LogInformation("Processed results have been relayed.");
var marked = await store.MarkAsync(next);
logger.LogInformation("Marked as processed: {next}", marked);
}
finally
{
logger.LogInformation(
"Finished scoped work, provider hash: {hash}.{nl}",
scope.ServiceProvider.GetHashCode(), Environment.NewLine);
}
}
}
}
}
V předchozím kódu, zatímco je aplikace spuštěná, služba na pozadí:
- Závisí na závislosti IServiceScopeFactoryna .
- Vytvoří IServiceScope pro řešení jiných služeb.
- Řeší služby s vymezeným oborem pro spotřebu.
- Pracuje na zpracování objektů a jejich následné předávání a nakonec je označí jako zpracované.
Z ukázkového zdrojového kódu si můžete prohlédnout, jak můžou implementace těžit z rozsahu IHostedService životnosti služby.
Služby s klíči
Od .NET 8 existuje podpora registrací služeb a vyhledávání na základě klíče, což znamená, že je možné zaregistrovat více služeb s jiným klíčem a tento klíč použít pro vyhledávání.
Představte si například případ, kdy máte různé implementace rozhraní IMessageWriter: MemoryMessageWriter a QueueMessageWriter.
Tyto služby můžete zaregistrovat pomocí přetížení metod registrace služby (vidět dříve), které podporují klíč jako parametr:
services.AddKeyedSingleton<IMessageWriter, MemoryMessageWriter>("memory");
services.AddKeyedSingleton<IMessageWriter, QueueMessageWriter>("queue");
Není key omezen na string. Může key být libovolný object , pokud typ správně implementuje Equals.
V konstruktoru třídy, která používá IMessageWriter, přidáte FromKeyedServicesAttribute k zadání klíče služby k vyřešení:
public class ExampleService
{
public ExampleService(
[FromKeyedServices("queue")] IMessageWriter writer)
{
// Omitted for brevity...
}
}
Viz také
- Vysvětlení základů injektáže závislostí v .NET
- Použití injektáže závislostí v .NET
- Pokyny pro injektáž závislostí
- Injektáž závislostí v ASP.NET Core
- Vzory konferencí NDC pro vývoj aplikací DI
- Princip explicitních závislostí
- Kontajnery inverze řízení a vzor injekce závislostí (Martin Fowler)
- V úložišti github.com/dotnet/extensions by se měly vytvořit chyby DI.