如何在 System.CommandLine 中使用中介軟體
重要
System.CommandLine
目前為預覽版,而此文件適用於版本 2.0 搶鮮版 (Beta) 4。
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
本文說明如何在使用 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]
,中介軟體會寫出 "Hi!"。 發生這種情況時,不會叫用命令的一般處理常式。 因為中介軟體不會呼叫 next
委派,所以不會叫用它。
在此範例中,context
是 InvocationContext,這是一種 singleton 結構,可作為整個命令處理程序的「根」。 這是 System.CommandLine
中功能最強大的結構。 它在中介軟體中有兩個主要用途:
- 它提供 BindingContext、Parser、Console 和 HelpBuilder 的存取權,以擷取中介軟體自身自訂邏輯所需的相依性。
- 您可以設定 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!