Aracılığıyla paylaş


Ayrıştırma ve çağırma içinde System.CommandLine

Önemli

System.CommandLine şu anda ÖNİzLEME aşamasındadır ve bu belge 2.0 beta 5 sürümüne yöneliktir. Bazı bilgiler, yayımlanmadan önce önemli ölçüde değiştirilebilen yayın öncesi ürünle ilgilidir. Microsoft, burada sağlanan bilgilerle ilgili olarak açık veya zımni hiçbir garanti vermez.

System.CommandLine komut satırı ayrıştırma ve eylem çağırma arasında net bir ayrım sağlar. Ayrıştırma işlemi, komut satırı girişini ayrıştırma ve ayrıştırılan değerleri (ve ayrıştırma hatalarını) içeren bir System.CommandLine.ParseResult nesne oluşturmakla sorumludur. Eylem çağırma işlemi ayrıştırılmış komut, seçenek veya yönergeyle ilişkili eylemi çağırmaktan sorumludur (bağımsız değişkenlerin eylemleri olamaz).

Başlangıç Get started with System.CommandLine öğreticimizden aşağıdaki örnekte, ParseResult komut satırı girdisi ayrıştırılarak oluşturulmuştur. Hiçbir eylem tanımlanmamış veya çağrılmamış:

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

Belirli bir komut (veya yönerge veya seçenek) başarıyla ayrıştırıldığında bir eylem çağrılır. Eylem, bir System.CommandLine.ParseResult parametresi alan ve bir int çıkış kodu döndüren bir temsilcidir (zaman uyumsuz eylemler de kullanılabilir). Çıkış kodu yöntemi tarafından döndürülür ve komutun System.CommandLine.Parsing.ParseResult.Invoke başarıyla yürütülerek yürütülmediğini belirtmek için kullanılabilir.

Başlangıç Eğitimi ile System.CommandLine öğreticimizdeki aşağıdaki örnekte, eylem kök komutu için tanımlanır ve komut satırı girdisi ayrıştırıldıktan sonra çağrılır.

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

, System.CommandLine.Help.HelpOptionveya System.CommandLine.VersionOptiongibi System.CommandLine.Completions.SuggestDirectivebazı yerleşik simgeler önceden tanımlanmış eylemlerle birlikte gelir. Bu simgeler, oluşturduğunuz sırada kök komutuna otomatik olarak eklenir ve onu çalıştırdığınızda System.CommandLine.Parsing.ParseResult, onlar "hemen çalışır." Eylemleri kullanmak, uygulama mantığınıza odaklanmanızı sağlarken, kitaplık yerleşik simgeler için ayrıştırma ve çağırma eylemlerini gerçekleştirir. İsterseniz ayrıştırma işlemine bağlı kalıp herhangi bir eylem tanımlamayabilirsiniz (yukarıdaki ilk örnekte olduğu gibi).

AyrıştırmaSonucu

türü System.CommandLine.Parsing.ParseResult , komut satırı girişini ayrıştırma sonuçlarını temsil eden bir sınıftır. Seçenekler ve bağımsız değişkenler için ayrıştırılmış değerleri almak için bunu kullanmanız gerekir (eylemleri kullanıp kullanmadığınız fark etmez). Ayrıştırma hataları veya eşleşmeyen belirteçler olup olmadığını da de kontrol edebilirsiniz.

GetValue

yöntemi, System.CommandLine.Parsing.ParseResult.GetValue<T> seçeneklerin ve bağımsız değişkenlerin değerlerini almanıza olanak tanır:

int integer = parseResult.GetValue(delayOption);
string? message = parseResult.GetValue(messageOption);

Değerleri ada göre de alabilirsiniz, ancak bu, almak istediğiniz değerin türünü belirtmenizi gerektirir.

Aşağıdaki örnekte, kök komut oluşturmak için C# koleksiyonu başlatıcıları kullanılır:

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

Ardından GetValue yöntemini kullanarak değerleri ada göre alır.

rootCommand.SetAction(parseResult =>
{
    int integer = parseResult.GetValue<int>("--delay");
    string? message = parseResult.GetValue<string>("--message");

    DisplayIntAndString(integer, message);
});

GetValue yönteminin bu aşırı yüklemesi, ayrıştırılmış komut bağlamında, belirtilen simge adı için ayrıştırılmış veya varsayılan değeri getirir (tüm sembol ağacı yerine). Simge adını kabul eder, diğer adını kabul etmez.

Hataları ayrıştırma

özelliği, System.CommandLine.Parsing.ParseResult.Errors ayrıştırma işlemi sırasında oluşan ayrıştırma hatalarının listesini içerir. Her hata, hata iletisi ve hataya neden olan belirteç gibi hata hakkındaki bilgileri içeren bir System.CommandLine.Parsing.ParseError nesneyle temsil edilir.

yöntemini çağırdığınızda System.CommandLine.Parsing.ParseResult.Invoke , ayrıştırma işleminin başarılı olup olmadığını gösteren bir çıkış kodu döndürür. Ayrıştırma hataları varsa çıkış kodu sıfır değildir ve tüm ayrıştırma hataları standart hataya yazdırılır.

System.CommandLine.Parsing.ParseResult.Invoke yöntemini çağırmıyorsanız, hataları kendi başınıza işlemeli; örneğin, yazdırarak yönetmelisiniz.

foreach (ParseError parseError in parseResult.Errors)
{
    Console.Error.WriteLine(parseError.Message);
}
return 1;

Eşleşmeyen belirteçler

System.CommandLine.Parsing.ParseResult.UnmatchedTokens özelliği ayrıştırılmış ancak yapılandırılmış hiçbir komut, seçenek veya bağımsız değişkenle eşleşmemiş belirteçlerin listesini içerir.

Eşleşmeyen belirteçlerin listesi, sarmalayıcı gibi davranan komutlarda kullanışlıdır. Sarıcı komut bir grup belirteç alır ve bunları başka bir komut veya uygulamaya iletir. sudo Linux'taki komut bir örnektir. Kimliğine bürünmek için bir kullanıcının adını alır ve ardından çalıştırılacak bir komut alır. Örneğin:

sudo -u admin apt update

Bu komut satırı, apt update komutunu kullanıcısı adminolarak çalıştırır.

Bunun gibi bir sarmalayıcı komutu uygulamak için komut özelliğini System.CommandLine.Command.TreatUnmatchedTokensAsErrors olarak falseayarlayın. Ardından System.CommandLine.Parsing.ParseResult.UnmatchedTokens özelliği, komutuna açıkça ait olmayan tüm bağımsız değişkenleri içerir. Önceki örnekte ParseResult.UnmatchedTokens içindeki apt ve update belirteçleri bulunur.

Eylemler

Eylemler, bir komut (veya bir seçenek veya yönerge) başarıyla ayrıştırıldığında çağrılan temsilcilerdir. Bir System.CommandLine.ParseResult parametre alırlar ve bir int (veya Task<int>) çıkış kodu döndürürler. Çıkış kodu, eylemin başarıyla yürütülerek yürütülmediğini göstermek için kullanılır.

System.CommandLine soyut bir temel sınıf System.CommandLine.CommandLineAction ve iki türetilmiş sınıf sağlar: System.CommandLine.SynchronousCommandLineAction ve System.CommandLine.AsynchronousCommandLineAction. İlki çıkış int kodu döndüren zaman uyumlu eylemler için kullanılırken, ikincisi çıkış kodu döndüren Task<int> zaman uyumsuz eylemler için kullanılır.

Eylem tanımlamak için türetilmiş bir tür oluşturmanız gerekmez. Bir komut için bir eylem ayarlamak üzere System.CommandLine.Command.SetAction yöntemini kullanabilirsiniz. Eşzamanlı işlem, bir System.CommandLine.ParseResult parametresi alan ve bir int çıkış kodu döndüren bir temsilci olabilir. Zaman uyumsuz eylem, bir System.CommandLine.ParseResult ve CancellationToken parametrelerini alan ve bir Task<int> döndüren bir temsilci olabilir.

rootCommand.SetAction(parseResult =>
{
    FileInfo parsedFile = parseResult.GetValue(fileOption);
    ReadFile(parsedFile);
    return 0;
});

Zaman uyumsuz eylemler

Zaman uyumlu ve zaman uyumsuz eylemler aynı uygulamada karıştırılmamalıdır. Zaman uyumsuz eylemler kullanmak istiyorsanız, uygulamanızın yukarıdan aşağıya doğru zaman uyumsuz olması gerekir. Bu, tüm eylemlerin zaman uyumsuz olması gerektiği ve System.CommandLine.Command.SetAction yöntemini, çıkış kodu döndüren bir temsilciyi kabul eden Task<int> şeklinde kullanmanız gerektiği anlamına gelir. Ayrıca, eylem temsilcisine geçirilen CancellationToken, dosya G/Ç işlemleri veya ağ istekleri gibi iptal edilebilecek tüm yöntemlere daha fazla iletilmelidir.

Bunun üzerine, System.CommandLine.Parsing.ParseResult.InvokeAsync yöntemi yerine System.CommandLine.Parsing.ParseResult.Invoke yönteminin kullanıldığından emin olmanız gerekir. Bu yöntem zaman uyumsuzdur ve bir Task<int> çıkış kodu döndürür. Ayrıca eylemi iptal etmek için kullanılabilecek isteğe bağlı CancellationToken bir parametre kabul eder.

Önceki kod, yalnızca SetAction yerine bir ParseResult ve CancellationToken alan bir ParseResult aşırı yükleme kullanır.

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

İşlem sonlandırma zaman aşımı

System.CommandLine.CommandLineConfiguration.ProcessTerminationTimeout, çağrılar sırasında her zaman uyumsuz eyleme aktarılan bir aracılığıyla işlem sonlandırmanın (+SIGINT, SIGTERM, CancellationToken) sinyal ve işlenmesini etkinleştirir. Varsayılan olarak etkindir (2 saniye), ancak devre dışı bırakmak için null olarak ayarlayabilirsiniz.

Etkinleştirildiğinde, eylem belirtilen zaman aşımı içinde tamamlanmazsa işlem sonlandırılır. Bu, sonlandırmayı düzgün bir şekilde işlemek için kullanışlıdır, örneğin işlem sonlandırılana kadar durumu kaydederek.

Önceki paragraftaki örnek kodu test etmek için, komutu yüklenmesi biraz zaman alacak bir URL ile çalıştırın ve yüklenmesi tamamlanmadan önce CtrlC+ basın. macOS'ta Komut+Dönemi(.)'ne basın. Örneğin:

testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted

Çıkış kodları

Çıkış kodu, başarılı veya başarısız olduğunu belirten bir eylem tarafından döndürülen bir tamsayı değeridir. Kurala göre, çıkış kodu başarıyı 0 belirtirken sıfır olmayan değerler hata gösterir. Komut yürütme durumunu net bir şekilde iletmek için uygulamanızda anlamlı çıkış kodları tanımlamanız önemlidir.

Her SetAction yöntem, çıkış kodunun açık bir şekilde sağlanması gereken çıkış kodunu döndüren bir int temsilciyi kabul eden bir aşırı yüklemeye ve döndüren 0bir aşırı yüklemeye sahiptir.

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

Ayrıca bakınız

Ayrıştırma ve doğrulamayı System.CommandLine nasıl özelleştirebilirsiniz?System.CommandLine hakkında genel bilgi