Share via


Afhankelijkheidsinjectie configureren in System.CommandLine

Belangrijk

System.CommandLine bevindt zich momenteel in PREVIEW en deze documentatie is voor versie 2.0 beta 4. Sommige informatie heeft betrekking op voorlopige versie van het product dat aanzienlijk kan worden gewijzigd voordat het wordt vrijgegeven. Microsoft biedt geen enkele expliciete of impliciete garanties met betrekking tot de informatie die hier wordt verstrekt.

Gebruik een aangepaste binder om aangepaste typen in een opdrachthandler te injecteren.

We raden handler-specifieke afhankelijkheidsinjectie (DI) aan om de volgende redenen:

  • Opdrachtregel-apps zijn vaak kortstondige processen, waarbij opstartkosten een merkbare invloed kunnen hebben op de prestaties. Het optimaliseren van de prestaties is met name belangrijk wanneer tabvoltooiingen moeten worden berekend. Opdrachtregel-apps zijn in tegenstelling tot web- en GUI-apps, die meestal relatief langlopende processen zijn. Onnodige opstarttijd is niet geschikt voor processen met korte levensduur.
  • Wanneer een opdrachtregel-app met meerdere subopdrachten wordt uitgevoerd, wordt slechts één van deze subopdrachten uitgevoerd. Als een app afhankelijkheden configureert voor de subopdrachten die niet worden uitgevoerd, worden de prestaties onnodig verminderd.

Als u DI wilt configureren, maakt u een klasse die is afgeleid van BinderBase<T> waar T de interface is waarvoor u een exemplaar wilt injecteren. Haal in de GetBoundValue methode-onderdrukking het exemplaar op dat u wilt injecteren en retourneren. In het volgende voorbeeld wordt de standaardlogger-implementatie voor 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;
    }
}

Wanneer u de SetHandler methode aanroept, geeft u een exemplaar van de geïnjecteerde klasse door aan de lambda en geeft u een exemplaar van uw binderklasse door in de lijst met services:

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

De volgende code is een volledig programma dat de voorgaande voorbeelden bevat:

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

Zie ook

System.CommandLine Overzicht