Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
System.CommandLine poskytuje jasné oddělení mezi analýzou příkazového řádku a vyvoláním akce. Proces analýzy zodpovídá za analýzu vstupu příkazového řádku a vytvoření ParseResult objektu, který obsahuje analyzované hodnoty (a parsovat chyby). Proces vyvolání akce je zodpovědný za vyvolání akce přidružené k analyzovanýmu příkazu, možnosti nebo direktivě (argumenty nemůžou mít akce).
V následujícím příkladu z kurzu Začínáme s kurzem System.CommandLine se ParseResult vytvoří parsováním vstupu příkazového řádku. Nejsou definovány ani vyvolány žádné akce:
using System.CommandLine;
using System.CommandLine.Parsing;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "The file to read and display on the console."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
rootCommand.Options.Add(fileOption);
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.Errors.Count == 0 && parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
ReadFile(parsedFile);
return 0;
}
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
}
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
}
Akce se vyvolá, když se daný příkaz (nebo direktiva nebo možnost) úspěšně parsuje. Akce je delegát, který přijímá ParseResult argument a vrací ukončovací int kód (jsou k dispozici také asynchronní akce ). Ukončovací kód je vrácen metodou System.CommandLine.Parsing.ParseResult.Invoke a lze jej použít k označení, zda byl příkaz úspěšně spuštěn nebo ne.
V následujícím příkladu z kurzu Začínáme s kurzem System.CommandLine je akce definována pro kořenový příkaz a vyvolána po analýze vstupu příkazového řádku:
using System.CommandLine;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "The file to read and display on the console."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
rootCommand.Options.Add(fileOption);
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
ParseResult parseResult = rootCommand.Parse(args);
return parseResult.Invoke();
}
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
}
Některé předdefinované symboly, například System.CommandLine.Help.HelpOption, System.CommandLine.VersionOptiona System.CommandLine.Completions.SuggestDirective, jsou součástí předdefinovaných akcí. Tyto symboly se automaticky přidají do kořenového příkazu, když ho System.CommandLine.Parsing.ParseResult vytvoříte, a když System.CommandLine.Parsing.ParseResult vyvoláte, "samovolně fungují". Použití akcí umožňuje zaměřit se na logiku aplikace, zatímco knihovna se postará o parsování a vyvolání akcí pro vestavěné symboly. Pokud chcete, můžete se držet procesu analýzy a nedefinovat žádné akce (jako v prvním příkladu výše).
Výsledek analýzy
Třída ParseResult představuje výsledky analýzy vstupu příkazového řádku. Potřebujete ho použít k získání parsovaných hodnot pro možnosti a argumenty (bez ohledu na to, jestli používáte akce nebo ne). Můžete také zkontrolovat, jestli nedošlo k nějakým chybám analýzy nebo chybějícím tokenům.
GetValue
Metoda ParseResult.GetValue umožňuje načíst hodnoty možností a argumentů:
int integer = parseResult.GetValue(delayOption);
string? message = parseResult.GetValue(messageOption);
Můžete také získat hodnoty podle názvu, ale to vyžaduje, abyste zadali typ hodnoty, kterou chcete získat.
Následující příklad používá inicializátory kolekcí jazyka C#k vytvoření kořenového příkazu:
RootCommand rootCommand = new("Parameter binding example")
{
new Option<int>("--delay")
{
Description = "An option whose argument is parsed as an int."
},
new Option<string>("--message")
{
Description = "An option whose argument is parsed as a string."
}
};
Pak použije metodu GetValue k získání hodnot podle názvu:
rootCommand.SetAction(parseResult =>
{
int integer = parseResult.GetValue<int>("--delay");
string? message = parseResult.GetValue<string>("--message");
DisplayIntAndString(integer, message);
});
Tato přetížená verze funkce GetValue získá analyzovanou nebo výchozí hodnotu pro zadaný název symbolu v kontextu analyzovaného příkazu, nikoli celého stromu symbolů. Přijímá název symbolu, nikoli alias.
Parsování chyb
Vlastnost ParseResult.Errors obsahuje seznam chyb analýzy, ke kterým došlo během procesu analýzy. Každá chyba je reprezentována objektem ParseError , který obsahuje informace o chybě, například chybovou zprávu a token, který způsobil chybu.
Při volání ParseResult.Invoke(InvocationConfiguration) metody vrátí ukončovací kód, který označuje, zda analýza byla úspěšná nebo ne. Pokud došlo k nějakým chybám analýzy, ukončovací kód je nenulový a všechny chyby analýzy se vytisknou do standardní chyby.
Pokud metodu ParseResult.Invoke nezavoláte, musíte je sami zpracovat tak, že je vytisknete:
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
Neshodující se tokeny
Tato UnmatchedTokens vlastnost obsahuje seznam tokenů, které byly analyzovány, ale neodpovídají žádnému nakonfigurovanýmu příkazu, možnosti nebo argumentu.
Seznam nespárovaných tokenů je užitečný v příkazech, které se chovají jako obálky. Příkaz obálky vezme sadu tokenů a předá je jinému příkazu nebo aplikaci. Příkladem sudo je příkaz v Linuxu. Bere jméno uživatele k zosobnění a poté příkaz ke spuštění. Například následující příkaz spustí apt update příkaz jako uživatel admin:
sudo -u admin apt update
Chcete-li implementovat příkaz obálky, jako je tento, nastavte vlastnost System.CommandLine.Command.TreatUnmatchedTokensAsErrors příkazu na false.
System.CommandLine.Parsing.ParseResult.UnmatchedTokens Vlastnost pak bude obsahovat všechny argumenty, které explicitně nepatří do příkazu. V předchozím příkladu by ParseResult.UnmatchedTokens obsahoval tokeny apt a update.
Akce
Akce působí jako delegáti, kteří jsou vyvoláni při úspěšné analýze příkazu, možnosti nebo direktivy. Přebírají ParseResult argument a vrátí (neboint) ukončovací Task<int> kód. Ukončovací kód slouží k označení, jestli byla akce úspěšně spuštěna nebo ne.
System.CommandLine poskytuje abstraktní základní třídu CommandLineAction a dvě odvozené třídy: SynchronousCommandLineAction a AsynchronousCommandLineAction. První se používá pro synchronní akce, které vracejí int ukončovací kód, zatímco druhý se používá pro asynchronní akce, které vracejí Task<int> ukončovací kód.
K definování akce nemusíte vytvářet odvozený typ. Pomocí metody SetAction můžete nastavit akci pro příkaz. Synchronní akcí může být delegát, který přijímá ParseResult argument a vrací ukončovací int kód. Asynchronní akce může být delegát, který přijímá ParseResult a CancellationToken argumenty a vrací hodnotu Task<int>.
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
Asynchronní akce
Synchronní a asynchronní akce by neměly být ve stejné aplikaci smíšené. Pokud chcete použít asynchronní akce, musí být vaše aplikace v celém prostředí asynchronní. To znamená, že všechny akce by měly být asynchronní a měli byste použít metodu System.CommandLine.Command.SetActionTask<int> , která přijímá delegáta vracející ukončovací kód. Kromě toho musí CancellationToken být delegát akce předán dále všem metodám, které je možné zrušit, jako jsou vstupně-výstupní operace souborů nebo síťové požadavky.
Musíte také zajistit, aby ParseResult.InvokeAsync(InvocationConfiguration, CancellationToken) se metoda používala místo Invoke. Tato metoda je asynchronní a vrací ukončovací Task<int> kód. Přijímá také volitelný CancellationToken parametr, který lze použít ke zrušení akce.
Následující kód používá SetAction přetížení, které získá ParseResult a CancellationToken spíše než jen ParseResult:
static Task<int> Main(string[] args)
{
Option<string> urlOption = new("--url", "A URL.");
RootCommand rootCommand = new("Handle termination example") { urlOption };
rootCommand.SetAction((ParseResult parseResult, CancellationToken cancellationToken) =>
{
string? urlOptionValue = parseResult.GetValue(urlOption);
return DoRootCommand(urlOptionValue, cancellationToken);
});
return rootCommand.Parse(args).InvokeAsync();
}
public static async Task<int> DoRootCommand(
string? urlOptionValue, CancellationToken cancellationToken)
{
using HttpClient httpClient = new();
try
{
await httpClient.GetAsync(urlOptionValue, cancellationToken);
return 0;
}
catch (OperationCanceledException)
{
await Console.Error.WriteLineAsync("The operation was aborted");
return 1;
}
}
Časový limit pro ukončení procesu
ProcessTerminationTimeout umožňuje signalizaci a zpracování ukončení procesu (Ctrl+C, SIGINT, SIGTERM) prostřednictvím CancellationToken předávané každé asynchronní akce během vyvolání. Ve výchozím nastavení je povoleno (2 sekundy), ale můžete ji nastavit na null pro zakázání.
Pokud je povoleno, a pokud akce není dokončena v zadaném časovém limitu, proces bude ukončen. To je užitečné pro řádné zpracování ukončení, například uložením stavu před ukončením procesu.
Pokud chcete otestovat vzorový kód z předchozího odstavce, spusťte příkaz s adresou URL, která chvíli načte a než se dokončí načítání, stiskněte ctrl+C. V systému macOS stiskněte command+Period(.). Například:
testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted
Ukončovací kódy
Ukončovací kód je celočíselná hodnota vrácená akcí označující její úspěch nebo selhání. Podle konvence ukončovací 0 kód označuje úspěch, zatímco jakákoli nenulová hodnota indikuje chybu. Je důležité definovat smysluplné ukončovací kódy ve vaší aplikaci, aby bylo možné jasně sdělit stav provádění příkazů.
Každá SetAction metoda má přetížení, které přijímá delegáta vracející kód ukončení int, kde musí být kód ukončení zadán explicitně, a přetížení, které vrací 0.
static int Main(string[] args)
{
Option<int> delayOption = new("--delay");
Option<string> messageOption = new("--message");
RootCommand rootCommand = new("Parameter binding example")
{
delayOption,
messageOption
};
rootCommand.SetAction(parseResult =>
{
Console.WriteLine($"--delay = {parseResult.GetValue(delayOption)}");
Console.WriteLine($"--message = {parseResult.GetValue(messageOption)}");
// Value returned from the action delegate is the exit code.
return 100;
});
return rootCommand.Parse(args).Invoke();
}