Поделиться через


Использование ПО промежуточного слоя в System.CommandLine

Внимание

System.CommandLine в настоящее время находится в предварительной версии, и эта документация предназначена для версии 2.0 бета-версии 4. Некоторые сведения относятся к предварительному выпуску продукта, который может быть существенно изменен до его выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В этой статье объясняется, как работать с ПО промежуточного слоя в приложениях командной строки, созданных с помощью библиотеки System.CommandLine . Использование ПО промежуточного слоя — это расширенная тема, которую большинству System.CommandLine пользователей не нужно учитывать.

Общие сведения о ПО промежуточного слоя

Хотя каждая команда имеет обработчик, который System.CommandLine будет направляться на основе входных данных, существует также механизм для короткого замыкания или изменения входных данных перед вызовом логики приложения. Между анализом и вызовом существует цепочка ответственности, которую можно настроить. Ряд встроенных функций System.CommandLine использования этой возможности. Вот как --help--version и параметры коротких вызовов обработчика.

Каждый вызов в конвейере может выполнять действия в зависимости от ParseResult начала и возврата или вызова следующего элемента в конвейере. Его ParseResult можно заменить даже на этом этапе. Последний вызов в цепочке — это обработчик указанной команды.

Добавление в конвейер ПО промежуточного слоя

Вызов этого конвейера можно добавить, вызвав CommandLineBuilderExtensions.AddMiddleware. Ниже приведен пример кода, который включает пользовательскую директиву. После создания корневой команды с именем rootCommandкод добавляет параметры, аргументы и обработчики. Затем добавляется ПО промежуточного слоя:

var commandLineBuilder = new CommandLineBuilder(rootCommand);

commandLineBuilder.AddMiddleware(async (context, next) =>
{
    if (context.ParseResult.Directives.Contains("just-say-hi"))
    {
        context.Console.WriteLine("Hi!");
    }
    else
    {
        await next(context);
    }
});

commandLineBuilder.UseDefaults();
var parser = commandLineBuilder.Build();
await parser.InvokeAsync(args);

В приведенном выше коде ПО промежуточного слоя записывает сообщение "Привет!", если директива [just-say-hi] найдена в результате синтаксического анализа. В этом случае обычный обработчик команды не вызывается. Он не вызывается, так как ПО промежуточного next слоя не вызывает делегат.

В примере context используется InvocationContextоднотонная структура, которая выступает в качестве корневого элемента всего процесса обработки команд. Это самая мощная структура с System.CommandLineточки зрения возможностей. Существует два основных использования для него в по промежуточном слоях:

  • Он предоставляет доступ к BindingContextзависимостям, HelpBuilderParserConsoleкоторым требуется по промежуточному слоям для пользовательской логики.
  • Вы можете задать InvocationResult или ExitCode свойства, чтобы завершить обработку команд коротким способом. Примером является --help вариант, который реализуется таким образом.

Вот полная программа, включая обязательные using директивы.

using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;

class Program
{
    static async Task Main(string[] args)
    {
        var delayOption = new Option<int>("--delay");
        var messageOption = new Option<string>("--message");

        var rootCommand = new RootCommand("Middleware example");
        rootCommand.Add(delayOption);
        rootCommand.Add(messageOption);

        rootCommand.SetHandler((delayOptionValue, messageOptionValue) =>
            {
                DoRootCommand(delayOptionValue, messageOptionValue);
            },
            delayOption, messageOption);

        var commandLineBuilder = new CommandLineBuilder(rootCommand);

        commandLineBuilder.AddMiddleware(async (context, next) =>
        {
            if (context.ParseResult.Directives.Contains("just-say-hi"))
            {
                context.Console.WriteLine("Hi!");
            }
            else
            {
                await next(context);
            }
        });

        commandLineBuilder.UseDefaults();
        var parser = commandLineBuilder.Build();
        await parser.InvokeAsync(args);
    }

    public static void DoRootCommand(int delay, string message)
    {
        Console.WriteLine($"--delay = {delay}");
        Console.WriteLine($"--message = {message}");
    }
}

Ниже приведен пример командной строки и полученный результат из предыдущего кода:

myapp [just-say-hi] --delay 42 --message "Hello world!"
Hi!

См. также

Обзор System.CommandLine