Como usar middleware em System.CommandLine
Importante
System.CommandLine
está atualmente em PREVIEW, e esta documentação é para a versão 2.0 beta 4.
Algumas informações estão relacionadas ao produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Este artigo explica como trabalhar com middleware em aplicativos de linha de comando criados com a System.CommandLine
biblioteca. O uso de middleware é um tópico avançado que a maioria dos System.CommandLine
usuários não precisará considerar.
Introdução ao middleware
Embora cada comando tenha um manipulador que será encaminhado com base na entrada, também há um mecanismo para curto-circuito ou alteração da entrada antes que System.CommandLine
a lógica do aplicativo seja invocada. Entre a análise e a invocação, há uma cadeia de responsabilidade, que você pode personalizar. Uma série de recursos internos de System.CommandLine
fazer uso dessa capacidade. É assim que o --help
curto-circuito e --version
as opções chamam o seu manipulador.
Cada chamada no pipeline pode tomar medidas com base no ParseResult e retornar antecipadamente, ou optar por chamar o próximo item no pipeline. O ParseResult
pode até ser substituído durante esta fase. A última chamada na cadeia é o manipulador para o comando especificado.
Adicionar ao pipeline de middleware
Você pode adicionar uma chamada a esse pipeline chamando CommandLineBuilderExtensions.AddMiddleware. Aqui está um exemplo de código que habilita uma diretiva personalizada. Depois de criar um comando raiz chamado rootCommand
, o código como de costume adiciona opções, argumentos e manipuladores. Em seguida, o middleware é adicionado:
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);
No código anterior, o middleware escreve "Oi!" se a diretiva [just-say-hi]
for encontrada no resultado da análise. Quando isso acontece, o manipulador normal do comando não é invocado. Ele não é invocado porque o middleware não chama o next
delegado.
No exemplo, context
é InvocationContext, uma estrutura singleton que atua como a "raiz" de todo o processo de manipulação de comandos. Esta é a estrutura mais poderosa em System.CommandLine
termos de capacidades. Existem dois usos principais para ele no middleware:
- Ele fornece acesso ao BindingContext, Parser, Consolee HelpBuilder para recuperar dependências que um middleware requer para sua lógica personalizada.
- Você pode definir as propriedades ou ExitCode para encerrar o InvocationResult processamento de comandos de forma curto-circuitada. Um exemplo é a opção, que é implementada
--help
desta forma.
Aqui está o programa completo, incluindo as diretivas necessárias 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}");
}
}
Aqui está um exemplo de linha de comando e saída resultante do código anterior:
myapp [just-say-hi] --delay 42 --message "Hello world!"
Hi!