Partager via


Guide pratique pour configurer l’injection de dépendances dans System.CommandLine

Important

System.CommandLine est actuellement une PRÉVERSION et cette documentation concerne la version 2.0 beta 4. Certaines informations portent sur la préversion du produit qui est susceptible d’être en grande partie modifiée avant sa publication. Microsoft exclut toute garantie, expresse ou implicite, concernant les informations fournies ici.

Utilisez un binder personnalisé pour injecter des types personnalisés dans un gestionnaire de commandes.

Nous recommandons l’injection de dépendances spécifique au gestionnaire pour les raisons suivantes :

  • Les applications en ligne de commande sont souvent des processus de courte durée, dans lesquels le coût de démarrage peut avoir un impact notable sur les performances. L’optimisation des performances est particulièrement importante quand les complétions par tabulation doivent être calculées. Les applications en ligne de commande diffèrent des applications web et des applications GUI, qui ont tendance à être des processus dont la durée est relativement plus longue. Un temps de démarrage inutile n’est pas approprié pour les processus de courte durée.
  • Quand une application en ligne de commande qui comporte plusieurs sous-commandes est exécutée, une seule de ces sous-commandes est exécutée. Si une application configure des dépendances pour les sous-commandes qui ne s’exécutent pas, elle dégrade inutilement les performances.

Pour configurer l’injection de dépendances, créez une classe qui dérive de BinderBase<T>, où T correspond à l’interface pour laquelle vous souhaitez injecter une instance. Dans le remplacement de méthode GetBoundValue, récupérez et retournez l’instance à injecter. L’exemple suivant injecte l’implémentation du journaliseur par défaut pour ILogger :

public class MyCustomBinder : BinderBase<ILogger>
{
    protected override ILogger GetBoundValue(
        BindingContext bindingContext) => GetLogger(bindingContext);

    ILogger GetLogger(BindingContext bindingContext)
    {
        using ILoggerFactory loggerFactory = LoggerFactory.Create(
            builder => builder.AddConsole());
        ILogger logger = loggerFactory.CreateLogger("LoggerCategory");
        return logger;
    }
}

Quand vous appelez la méthode SetHandler, passez au lambda une instance de la classe injectée, puis passez une instance de votre classe binder dans la liste des services :

rootCommand.SetHandler(async (fileOptionValue, logger) =>
    {
        await DoRootCommand(fileOptionValue!, logger);
    },
    fileOption, new MyCustomBinder());

Le code suivant est un programme complet qui contient les exemples précédents :

using System.CommandLine;
using System.CommandLine.Binding;
using Microsoft.Extensions.Logging;

class Program
{
    static async Task Main(string[] args)
    {
        var fileOption = new Option<FileInfo?>(
              name: "--file",
              description: "An option whose argument is parsed as a FileInfo");

        var rootCommand = new RootCommand("Dependency Injection sample");
        rootCommand.Add(fileOption);

        rootCommand.SetHandler(async (fileOptionValue, logger) =>
            {
                await DoRootCommand(fileOptionValue!, logger);
            },
            fileOption, new MyCustomBinder());

        await rootCommand.InvokeAsync("--file scl.runtimeconfig.json");
    }

    public static async Task DoRootCommand(FileInfo aFile, ILogger logger)
    {
        Console.WriteLine($"File = {aFile?.FullName}");
        logger.LogCritical("Test message");
        await Task.Delay(1000);
    }

    public class MyCustomBinder : BinderBase<ILogger>
    {
        protected override ILogger GetBoundValue(
            BindingContext bindingContext) => GetLogger(bindingContext);

        ILogger GetLogger(BindingContext bindingContext)
        {
            using ILoggerFactory loggerFactory = LoggerFactory.Create(
                builder => builder.AddConsole());
            ILogger logger = loggerFactory.CreateLogger("LoggerCategory");
            return logger;
        }
    }
}

Voir aussi

Vue d’ensemble de System.CommandLine