Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Dans ce guide de démarrage rapide, vous créez une application console .NET qui crée manuellement un ServiceCollection et un ServiceProvider correspondant. Vous apprenez à inscrire des services et à les résoudre à l’aide de l’injection de dépendances (DI). Cet article utilise le package NuGet Microsoft.Extensions.DependencyInjection pour illustrer les principes de base de l'injection de dépendances dans .NET.
Note
Cet article ne tire pas parti des fonctionnalités de l’hôte générique . Pour obtenir un guide plus complet, consultez Utiliser l’injection de dépendances dans .NET.
Get started
Pour commencer, créez une application console .NET nommée DI.Basics. Dans Visual Studio, choisissez Fichier > nouveau > projet ou à l’aide de l’interface CLI .NET, entrez dotnet new console.
Ensuite, ajoutez une référence de package à Microsoft.Extensions.DependencyInjection dans le fichier projet. Après avoir ajouté le package, vérifiez que le projet ressemble au code XML suivant du fichier DI.Basics.csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
</ItemGroup>
</Project>
Bases de l’injection de dépendances
L’injection de dépendances est un modèle de conception que vous pouvez utiliser pour supprimer les dépendances codées en dur et rendre votre application plus gérable et testable. DI est une technique permettant d’atteindre l’inversion du contrôle (IoC) entre les classes et leurs dépendances.
Le package NuGet Microsoft.Extensions.DependencyInjection.Abstractions définit les abstractions pour l'injection de dépendances dans .NET :
- IServiceCollection: définit un contrat pour une collection de descripteurs de service.
- IServiceProvider: définit un mécanisme de récupération d’un objet de service.
- ServiceDescriptor: décrit un service avec son type de service, son implémentation et sa durée de vie.
Dans .NET, vous gérez l’DI en ajoutant des services et en les configurant dans un IServiceCollection. Après avoir inscrit des services, appelez la BuildServiceProvider méthode pour générer une IServiceProvider instance. Le IServiceProvider agit en tant que conteneur pour tous les services enregistrés, que vous utilisez pour résoudre les services.
Créer des exemples de services
Tous les services ne sont pas créés de façon égale. Certains services nécessitent une nouvelle instance chaque fois que le conteneur de services les obtient (transitoire), tandis que d’autres doivent être partagés entre les requêtes (scopé) ou pendant toute la durée de vie de l’application (singleton). Pour plus d’informations sur les durées de vie des services, consultez Durées de vie des services.
De même, certains services n’exposent qu’un type concret, tandis que d’autres sont exprimés sous la forme d’un contrat entre une interface et un type d’implémentation. Vous créez plusieurs variantes de services pour vous aider à illustrer ces concepts.
Créez un fichier C# nommé IConsole.cs et ajoutez le code suivant :
public interface IConsole
{
void WriteLine(string message);
}
Ce fichier définit une IConsole interface qui expose une méthode unique. WriteLine Ensuite, créez un fichier C# nommé DefaultConsole.cs et ajoutez le code suivant :
internal sealed class DefaultConsole : IConsole
{
public bool IsEnabled { get; set; } = true;
void IConsole.WriteLine(string message)
{
if (IsEnabled is false)
{
return;
}
Console.WriteLine(message);
}
}
Le code précédent représente l’implémentation par défaut de l’interface IConsole . La méthode WriteLine écrit conditionnellement sur la console en fonction de la propriété IsEnabled.
Conseil / Astuce
Le nommage d’une implémentation est un choix que votre équipe de développement doit accepter. Le Default préfixe est une convention commune pour indiquer une implémentation par défaut d’une interface, mais elle n’est pas obligatoire.
Ensuite, créez un fichier IGreetingService.cs et ajoutez le code C# suivant :
public interface IGreetingService
{
string Greet(string name);
}
Ajoutez ensuite un nouveau fichier C# nommé DefaultGreetingService.cs et ajoutez le code suivant :
internal sealed class DefaultGreetingService(
IConsole console) : IGreetingService
{
public string Greet(string name)
{
var greeting = $"Hello, {name}!";
console.WriteLine(greeting);
return greeting;
}
}
Le code précédent représente l’implémentation par défaut de l’interface IGreetingService . L’implémentation du service nécessite un IConsole paramètre de constructeur principal. La méthode Greet :
- Crée un
greetingélément donné .name - Appelle la
WriteLineméthode sur l’instanceIConsole. - Retourne
greetingà l’appelant.
La DefaultGreetingService classe montre que vous pouvez implémenter seal des services pour empêcher l’héritage et utiliser internal pour restreindre l'accès à l’assembly.
Le dernier service à créer est le fichier FarewellService.cs . Ajoutez le code C# suivant avant de continuer :
public class FarewellService(IConsole console)
{
public string SayGoodbye(string name)
{
var farewell = $"Goodbye, {name}!";
console.WriteLine(farewell);
return farewell;
}
}
Représente FarewellService un type concret, et non une interface. Vous devriez le déclarer sous forme de public pour le rendre accessible aux consommateurs. Contrairement à d’autres types d’implémentation de service que vous déclarez en tant que internal et sealed, ce code montre que tous les services ne doivent pas être des interfaces.
Mettre à jour la Program classe
Ouvrez le fichier Program.cs et remplacez le code existant par le code C# suivant :
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");
Le code précédent montre comment :
- Créez une
ServiceCollectioninstance. - Inscrivez et configurez les services dans le
ServiceCollection.- Le service
IConsoleutilisant la surcharge de la fabrique d'implémentation. Retourne unDefaultConsoletype avec laIsEnabledpropriété définie surtrue. - Service
IGreetingServiceavec un type d’implémentation correspondant deDefaultGreetingService. - Le
FarewellServiceservice en tant que type concret.
- Le service
- Générez l’élément
ServiceProviderà partir duServiceCollection. - Résolvez les services
IGreetingServiceetFarewellService. - Utilisez les services résolus pour saluer et dire au revoir à une personne nommée
David.
Si vous mettez à jour la propriété de la DefaultConsole à la valeur false, les méthodes Greet et SayGoodbye omettent d’écrire les messages résultants dans la console. Cette modification permet de démontrer que le IConsole service est injecté dans les IGreetingService services et FarewellService qu’il s’agit d’une dépendance qui influence le comportement de l’application.
Tous ces services sont enregistrés comme des singletons. Pour cet exemple, il fonctionne de façon identique si vous les inscrivez en tant que services éphémères ou à portée.
Important
Dans cet exemple artificiel, les durées de vie du service n’ont pas d’importance. Dans une application réelle, tenez soigneusement compte de la durée de vie de chaque service.
Exécuter l’exemple d’application
Pour exécuter l’exemple d’application, appuyez sur F5 dans Visual Studio ou Visual Studio Code, ou exécutez la dotnet run commande dans le terminal. Une fois l’application terminée, la sortie suivante s’affiche :
Hello, David!
Goodbye, David!
Descripteurs de service
Les API les plus souvent utilisées pour ajouter des services au ServiceCollection sont des méthodes d'extension génériques nommées selon leur durée de vie, telles que :
AddSingleton<TService>AddTransient<TService>AddScoped<TService>
Ces méthodes sont des méthodes pratiques qui créent une ServiceDescriptor instance et l’ajoutent au ServiceCollection. Il ServiceDescriptor s’agit d’une classe simple qui décrit un service avec son type de service, son type d’implémentation et sa durée de vie. Il peut également décrire les fabriques d’implémentation et les instances.
Pour chaque service que vous avez inscrit dans le ServiceCollection, vous pouvez appeler la Add méthode directement avec une ServiceDescriptor instance. Prenons les exemples suivants :
services.Add(ServiceDescriptor.Describe(
serviceType: typeof(IConsole),
implementationFactory: static _ => new DefaultConsole
{
IsEnabled = true
},
lifetime: ServiceLifetime.Singleton));
Le code précédent équivaut à la façon dont le IConsole service a été inscrit dans le ServiceCollection. La Add méthode ajoute une ServiceDescriptor instance qui décrit le IConsole service. La méthode statique ServiceDescriptor.Describe délègue à plusieurs constructeurs ServiceDescriptor. Considérez le code équivalent pour le IGreetingService service :
services.Add(ServiceDescriptor.Describe(
serviceType: typeof(IGreetingService),
implementationType: typeof(DefaultGreetingService),
lifetime: ServiceLifetime.Singleton));
Le code précédent décrit le IGreetingService service avec son type de service, son type d’implémentation et sa durée de vie. Enfin, tenez compte du code équivalent pour le FarewellService service :
services.Add(ServiceDescriptor.Describe(
serviceType: typeof(FarewellService),
implementationType: typeof(FarewellService),
lifetime: ServiceLifetime.Singleton));
Le code précédent décrit le type concret FarewellService comme les types de service et d’implémentation. Le service est enregistré en tant que service singleton.