Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article décrit l’inscription de groupes de services et de services fournis par le framework. Il fournit également des détails sur les méthodes d'extension d'enregistrement de service que .NET propose.
Enregistrer des groupes de services avec des méthodes d’extension
.NET utilise une convention pour inscrire un groupe de services associés. La convention consiste à utiliser une seule méthode d’extension Add{GROUP_NAME} pour inscrire tous les services requis par une fonctionnalité d’infrastructure. Par exemple, la méthode d’extension AddOptions inscrit tous les services requis pour l’utilisation des options.
Services fournis par le framework
Lorsque vous utilisez l’un des modèles hôtes ou générateur d’applications disponibles, les valeurs par défaut sont appliquées et les services sont inscrits par l’infrastructure. Prenez en compte certains des modèles d’hôte et de générateur d’applications les plus populaires :
- Host.CreateDefaultBuilder()
- Host.CreateApplicationBuilder()
- WebHost.CreateDefaultBuilder()
- WebApplication.CreateBuilder()
- WebAssemblyHostBuilder.CreateDefault
- MauiApp.CreateBuilder
Après avoir créé un constructeur à partir de l'une de ces API, les IServiceCollection services fournis par le cadre dépendent de la façon dont vous avez configuré l'hôte. Dans le cas des applications basées sur les modèles .NET, l’infrastructure inscrit des centaines de services.
Le tableau suivant répertorie un petit exemple de ces services inscrits dans l’infrastructure :
| Type de service | Durée de vie |
|---|---|
| Microsoft.Extensions.DependencyInjection.IServiceScopeFactory | Singleton |
| IHostApplicationLifetime | Singleton |
| Microsoft.Extensions.Logging.ILogger<TCategoryName> | Singleton |
| Microsoft.Extensions.Logging.ILoggerFactory | Singleton |
| Microsoft.Extensions.ObjectPool.ObjectPoolProvider | Singleton |
| Microsoft.Extensions.Options.IConfigureOptions<TOptions> | Transient |
| Microsoft.Extensions.Options.IOptions<TOptions> | Singleton |
| System.Diagnostics.DiagnosticListener | Singleton |
| System.Diagnostics.DiagnosticSource | Singleton |
Méthodes d’inscription
L’infrastructure fournit des méthodes d’extension d’inscription de service qui sont utiles dans des scénarios spécifiques :
| Méthode | Suppression automatique d’objets | Implémentations multiples | Passage d’args |
|---|---|---|---|
Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>()Exemple : services.AddSingleton<IMyDep, MyDep>(); |
Oui | Oui | Non |
Add{LIFETIME}<{SERVICE}>(sp => new {IMPLEMENTATION})Exemples : services.AddSingleton<IMyDep>(sp => new MyDep());services.AddSingleton<IMyDep>(sp => new MyDep(99)); |
Oui | Oui | Oui |
Add{LIFETIME}<{IMPLEMENTATION}>()Exemple : services.AddSingleton<MyDep>(); |
Oui | Non | Non |
AddSingleton<{SERVICE}>(new {IMPLEMENTATION})Exemples : services.AddSingleton<IMyDep>(new MyDep());services.AddSingleton<IMyDep>(new MyDep(99)); |
Non | Oui | Oui |
AddSingleton(new {IMPLEMENTATION})Exemples : services.AddSingleton(new MyDep());services.AddSingleton(new MyDep(99)); |
Non | Non | Oui |
Pour plus d’informations sur l’élimination de type, consultez Suppression des services.
L’inscription d’un service avec uniquement un type d’implémentation revient à inscrire ce service avec le même type d’implémentation et de service. Considérons par exemple le code suivant :
services.AddSingleton<ExampleService>();
Ceci équivaut à inscrire le service avec le service et l’implémentation des mêmes types :
services.AddSingleton<ExampleService, ExampleService>();
Cette équivalence explique pourquoi plusieurs implémentations d’un service ne peuvent pas être inscrites en utilisant les méthodes qui n’acceptent pas un type de service explicite. Ces méthodes peuvent inscrire plusieurs instances d’un service, mais elles partagent toutes les mêmes types d'implémentation .
Toutes les méthodes d’inscription de service peuvent être utilisées pour inscrire plusieurs instances de service du même type de service. Dans l’exemple suivant, AddSingleton est appelé deux fois avec IMessageWriter comme type de service. Le deuxième appel à AddSingleton remplace le précédent lorsqu’il est résolu en tant que IMessageWriter et s’ajoute au précédent lorsque plusieurs services sont résolus via IEnumerable<IMessageWriter>. Les services apparaissent dans l'ordre où ils ont été enregistrés lorsqu'ils sont résolus via 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();
L’exemple de code source précédent inscrit deux implémentations de 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);
}
}
ExampleService définit deux paramètres de constructeur : un seul IMessageWriteret un IEnumerable<IMessageWriter>.
IMessageWriter Il s’agit de la dernière implémentation à inscrire, tandis que la IEnumerable<IMessageWriter> représente toutes les implémentations inscrites.
L’infrastructure fournit également des méthodes d’extension TryAdd{LIFETIME}, qui inscrivent le service uniquement s’il n’y a pas encore d’implémentation inscrite.
Dans l’exemple suivant, l’appel à AddSingleton inscrit ConsoleMessageWriter en tant qu’implémentation pour IMessageWriter. L’appel à TryAddSingleton n’a aucun effet car IMessageWriter a déjà une implémentation inscrite :
services.AddSingleton<IMessageWriter, ConsoleMessageWriter>();
services.TryAddSingleton<IMessageWriter, LoggingMessageWriter>();
Le TryAddSingleton n’a aucun effet, car il a déjà été ajouté et l'instruction « try » échoue. Le ExampleService affirme ce qui suit :
public class ExampleService
{
public ExampleService(
IMessageWriter messageWriter,
IEnumerable<IMessageWriter> messageWriters)
{
Trace.Assert(messageWriter is ConsoleMessageWriter);
Trace.Assert(messageWriters.Single() is ConsoleMessageWriter);
}
}
Pour plus d’informations, consultez :
Les méthodes TryAddEnumerable(ServiceDescriptor) inscrivent le service uniquement en l’absence d’une implémentation du même type. Plusieurs services sont résolus par le biais de IEnumerable<{SERVICE}>. Lors de l’inscription des services, ajoutez une instance si l’un des mêmes types n’a pas déjà été ajouté. Les auteurs de bibliothèque utilisent TryAddEnumerable pour éviter d’inscrire plusieurs copies d’une implémentation dans le conteneur.
Dans l’exemple suivant, le premier appel à TryAddEnumerable inscrit MessageWriter en tant qu’implémentation pour IMessageWriter1. Le deuxième appel enregistre MessageWriter pour IMessageWriter2. Le troisième appel n’a aucun effet car IMessageWriter1 a déjà une implémentation inscrite de 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>());
L’inscription de service est indépendante de l’ordre, sauf lors de l’inscription de plusieurs implémentations du même type.
IServiceCollection est une collection d’objets ServiceDescriptor. L’exemple suivant montre comment inscrire un service en créant et en ajoutant un ServiceDescriptor :
string secretKey = Configuration["SecretKey"];
var descriptor = new ServiceDescriptor(
typeof(IMessageWriter),
_ => new DefaultMessageWriter(secretKey),
ServiceLifetime.Transient);
services.Add(descriptor);
Les méthodes intégrées Add{LIFETIME} utilisent la même approche. Par exemple, consultez le code source AddScoped.