Udostępnij za pośrednictwem


Jak skonfigurować iniekcję zależności w programie System.CommandLine

Ważne

System.CommandLine jest obecnie dostępna w wersji zapoznawczej, a ta dokumentacja dotyczy wersji 2.0 beta 4. Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed jego wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Używanie niestandardowego powiązania do wstrzykiwania typów niestandardowych do programu obsługi poleceń.

Zalecamy wstrzykiwanie zależności specyficzne dla programu obsługi (DI) z następujących powodów:

  • Aplikacje wiersza polecenia to często krótkotrwałe procesy, w których koszt uruchamiania może mieć zauważalny wpływ na wydajność. Optymalizacja wydajności jest szczególnie ważna, gdy należy obliczyć uzupełnianie kart. Aplikacje wiersza polecenia są w przeciwieństwie do aplikacji internetowych i graficznych interfejsu użytkownika, które zwykle są stosunkowo długotrwałym procesem. Niepotrzebny czas uruchamiania nie jest odpowiedni dla procesów krótkotrwałych.
  • Po uruchomieniu aplikacji wiersza polecenia z wieloma podpoleceniami zostanie wykonanych tylko jeden z tych podpolecenia. Jeśli aplikacja konfiguruje zależności dla podpolecenia, które nie są uruchamiane, niepotrzebnie obniża wydajność.

Aby skonfigurować di, utwórz klasę, która pochodzi z BinderBase<T> miejsca, w którym T jest interfejs, dla którego chcesz wstrzyknąć wystąpienie. W zastąpieniu GetBoundValue metody pobierz i zwróć wystąpienie, które chcesz wstrzyknąć. Poniższy przykład wprowadza domyślną implementację rejestratora dla elementu 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;
    }
}

Podczas wywoływania SetHandler metody przekaż do klasy lambda wystąpienie wprowadzonej klasy i przekaż wystąpienie klasy binder na liście usług:

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

Poniższy kod to kompletny program zawierający powyższe przykłady:

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;
        }
    }
}

Zobacz też

System.CommandLine Przegląd