Megosztás a következőn keresztül:


Oktatóanyag: Fájlalapú C#-programok létrehozása

A fájlalapú alkalmazások olyan programok , amelyek egyetlen *.cs fájlban találhatók, és a megfelelő projektfájl (*.csproj) nélkül vannak létrehozva és futtatva. A fájlalapú alkalmazások ideálisak a C# tanulásához, mert kevésbé összetettek: A teljes program egyetlen fájlban van tárolva. A fájlalapú alkalmazások parancssori segédprogramok létrehozásához is hasznosak. Unix-platformokon a fájlalapú alkalmazások a shebang direktívák #! használatával futtathatók. Ebben az útmutatóban Ön:

  • Hozzon létre egy fájlalapú programot.
  • Unix shebang (#!) támogatás hozzáadása.
  • Parancssori argumentumok olvasása.
  • Standard bemenet kezelése.
  • ASCII-rajzkimenet írása.
  • Parancssori argumentumok feldolgozása.
  • Elemezett parancssori eredmények használata.
  • Tesztelje a végleges alkalmazást.

Létrehoz egy fájlalapú programot, amely ASCII-művészetként ír szöveget. Az alkalmazás egyetlen fájlban található, nuGet-csomagokat használ, amelyek implementálják az alapvető funkciók némelyikét.

Előfeltételek

Fájlalapú program létrehozása

  1. Nyissa meg a Visual Studio Code-ot, és hozzon létre egy új fájlt.AsciiArt.cs Írja be a következő szöveget:

    Console.WriteLine("Hello, world!");
    
  2. Mentse a fájlt. Ezután nyissa meg az integrált terminált a Visual Studio Code-ban, és írja be a következőt:

    dotnet run AsciiArt.cs
    

A program első futtatásakor a dotnet gazdagép létrehozza a végrehajtható fájlt a forrásfájlból, ideiglenes mappában tárolja a buildösszetevőket, majd futtatja a létrehozott végrehajtható fájlt. Ezt a felhasználói élményt ismét begépelve dotnet run AsciiArt.cs ellenőrizheti. A gazdagép ezúttal azt határozza meg, dotnet hogy a végrehajtható fájl aktuális-e, és anélkül futtatja a végrehajtható fájlt, hogy újra létrejön. Nem lát buildkimenetet.

Az előző lépések azt mutatják, hogy a fájlalapú alkalmazások nem szkriptfájlok. Ezek olyan C#-forrásfájlok, amelyek egy ideiglenes mappában létrehozott projektfájllal készültek. A program létrehozásakor megjelenő kimenetsorok egyikének így kell kinéznie (Windows rendszeren):

AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll

Unix-platformokon a kimeneti mappa a következőhöz hasonló:

AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll

Ez a kimenet jelzi, hogy hol találhatók az ideiglenes fájlok és a buildkimenetek. Az oktatóanyag során, amikor szerkessze a forrásfájlt, a dotnet gazdagép a futtatás előtt frissíti a végrehajtható fájlt.

A fájlalapú alkalmazások normál C#-programok. Az egyetlen korlátozás az, hogy egy forrásfájlba kell írni őket. Használhat felső szintű utasításokat vagy klasszikus Main metódust belépési pontként. Bármilyen típust deklarálhat: osztályokat, interfészeket és szerkezeteket. Az algoritmusokat ugyanúgy strukturálhatja fájlalapú programokban, mint bármely C#-programban. Akár több névteret is deklarálhat a kód rendszerezéséhez. Ha úgy találja, hogy egy fájlalapú program túl nagy egy fájlhoz, átalakíthatja projektalapú programtá, és több fájlra oszthatja a forrást. A fájlalapú alkalmazások nagyszerű prototípus-készítő eszközök. Elkezdhet kísérletezni minimális többletterheléssel a fogalmak bizonyításához és algoritmusok létrehozásához.

Unix shebang (#!) támogatása

Megjegyzés:

Az irányelvek támogatása #! csak Unix-platformokra vonatkozik. A Windows nem rendelkezik hasonló irányelvvel egy C#-program közvetlen végrehajtásához. Windows rendszeren a parancssort kell használnia dotnet run .

Unix esetén közvetlenül futtathat fájlalapú alkalmazásokat, és a forrásfájl nevét a parancssorba írja be ahelyett, hogy a parancssorba dotnet runírná. Két módosítást kell végrehajtania:

  1. Végrehajtási engedélyek beállítása a forrásfájlon:

    chmod +x AsciiArt.cs
    
  2. Adja hozzá a shebang (#!) direktívát a AsciiArt.cs fájl első soraként:

    #!/usr/local/share/dotnet/dotnet run
    

A hely dotnet különböző unix-telepítések esetén eltérő lehet. A(z) which dotnet parancs használatával keresse meg a(z) dotnet gazdagépet a környezetében.

Alternatív megoldásként használhatja a #!/usr/bin/env dotnet -t, hogy a PATH környezeti változóból automatikusan feloldja a dotnet elérési útját.

#!/usr/bin/env dotnet

A két módosítás elvégzése után a programot közvetlenül a parancssorból futtathatja:

./AsciiArt.cs

Ha szeretné, eltávolíthatja a bővítményt, hogy gépelhesse ./AsciiArt . Windows használata esetén is hozzáadhatja a #! forrásfájlhoz. A Windows parancssora nem támogatja #!, de a C#-fordító minden platformon engedélyezi ezt az irányelvet a fájlalapú alkalmazásokban.

Parancssori argumentumok olvasása

Most írja be a parancssor összes argumentumát a kimenetbe.

  1. Cserélje le az aktuális tartalmat AsciiArt.cs a következő kódra:

    if (args.Length > 0)
    {
        string message = string.Join(' ', args);
        Console.WriteLine(message);
    }
    
  2. Ezt a verziót a következő parancs beírásával futtathatja:

    dotnet run AsciiArt.cs -- This is the command line.
    

    A -- beállítás azt jelzi, hogy a következő parancsargumentumokat át kell adni az AsciiArt programnak. Az argumentumok This is the command line. karakterláncok tömbjeként lesznek átadva, ahol minden sztring egy szó: This, , is, thecommandés line..

Ez a verzió az alábbi új fogalmakat mutatja be:

  • A parancssori argumentumokat a program az előre definiált változó argshasználatával továbbítja. A args változó sztringek tömbje: string[]. Ha a hossz args 0, az azt jelenti, hogy nem adtak meg argumentumokat. Ellenkező esetben az argumentumlistában szereplő összes szó a tömb megfelelő bejegyzésében lesz tárolva.
  • A string.Join metódus több sztringet illeszt egyetlen sztringbe a megadott elválasztójellel. Ebben az esetben az elválasztó egy szóköz.
  • Console.WriteLine A sztringet a standard kimeneti konzolra írja, majd egy új sort.

Standard bemenet kezelése

Ez helyesen kezeli a parancssori argumentumokat. Most adja hozzá a kódot a standard bemenet (stdin) olvasási bemenetének kezeléséhez parancssori argumentumok helyett.

  1. Adja hozzá a következő else záradékot az if előző kódban hozzáadott utasításhoz:

    else
    {
        while (Console.ReadLine() is string line && line.Length > 0)
        {
            Console.WriteLine(line);
        }
    }
    

    Az előző kód beolvassa a konzol bemenetét, amíg egy üres sor vagy egy null szöveg be nem olvasható. (A Console.ReadLine metódus akkor ad vissza értéket null , ha a bemeneti stream a ctrl+C billentyűkombinációval van bezárva.)

  2. A standard bemenet olvasásának teszteléséhez hozzon létre egy új szövegfájlt ugyanabban a mappában. Nevezze el a fájlt input.txt , és adja hozzá a következő sorokat:

    Hello from ...
    dotnet!
    
    You can create
    file-based apps
    in .NET 10 and
    C# 14
    
    Have fun writing
    useful utilities
    

    Tartsa rövidre a sorokat, hogy megfelelően formázzák őket, amikor hozzáadja a funkciót az ASCII-művészet használatához.

  3. Futtassa újra a programot.

    Bash használatával:

    cat input.txt | dotnet run AsciiArt.cs
    

    Vagy a PowerShell használatával:

    Get-Content input.txt | dotnet run AsciiArt.cs
    

A program most már elfogadhatja a parancssori argumentumokat vagy a standard bemenetet.

ASCII Art-kimenet írása

Ezután vegyen fel egy olyan csomagot, amely támogatja az ASCII-művészetet, a Colorful.Console-t. Ha csomagot szeretne hozzáadni egy fájlalapú programhoz, használja az #:package irányelvet.

  1. Adja hozzá a következő irányelvet az irányelv után a #! AsciiArt.cs fájlban:

    #:package Colorful.Console@1.2.15
    

    Fontos

    Az oktatóanyag legutóbbi frissítésekor ez a verzió 1.2.15 volt a Colorful.Console csomag legújabb verziója. Ellenőrizze a csomag NuGet-oldalán a legújabb verziót, és győződjön meg arról, hogy a legújabb biztonsági javításokkal rendelkező csomagverziót használja.

  2. Módosítsa a metódus használatára Console.WriteLine felhívó Colorful.Console.WriteAscii sorokat:

    async Task WriteAsciiArt(AsciiMessageOptions options)
    {
        foreach (string message in options.Messages)
        {
            Colorful.Console.WriteAscii(message);
            await Task.Delay(options.Delay);
        }
    }
    
  3. Futtassa a programot, és az ASCII art kimenete jelenik meg a visszhangzott szöveg helyett.

Folyamatparancs beállításai

Ezután adjunk hozzá parancssori elemzést. Az aktuális verzió minden szót más kimeneti sorként ír. A hozzáadott parancssori argumentumok két funkciót támogatnak:

  1. Több szó idézőjele, amelyeket egy sorra kell írni:

    AsciiArt.cs "This is line one" "This is another line" "This is the last line"
    
  2. Adjon hozzá egy --delay lehetőséget az egyes sorok közötti szünetre:

    AsciiArt.cs --delay 1000
    

A felhasználóknak képesnek kell lenniük arra, hogy mindkét argumentumot együtt használják.

A legtöbb parancssori alkalmazásnak elemeznie kell a parancssori argumentumokat a beállítások, parancsok és felhasználói bevitel hatékony kezeléséhez. A System.CommandLine kódtár átfogó képességeket biztosít a parancsok, alparancsok, beállítások és argumentumok kezeléséhez, így a parancssori bemenet elemzése helyett az alkalmazás által végzett feladatokra összpontosíthat.

A System.CommandLine kódtár számos fontos előnnyel jár:

  • Automatikus súgószöveg-létrehozás és -ellenőrzés.
  • A POSIX és a Windows parancssori konvenciók támogatása.
  • Beépített lapkiegészítési képességek.
  • Konzisztens elemzési viselkedés az alkalmazásokban.
  1. Adja hozzá a System.CommandLine csomagot. Adja hozzá ezt az irányelvet a meglévő csomagra vonatkozó irányelv után:

    #:package System.CommandLine@2.0.0
    

    Fontos

    Az oktatóanyag legutóbbi frissítésekor ez a verzió 2.0.0 volt a legújabb verzió. Ha újabb verzió érhető el, a legújabb verzióval győződjön meg arról, hogy a legújabb biztonsági csomagokkal rendelkezik. Ellenőrizze a csomag NuGet-oldalán a legújabb verziót, és győződjön meg arról, hogy a legújabb biztonsági javításokkal rendelkező csomagverziót használja.

  2. Adja hozzá a szükséges utasításokat a fájl tetején (az és #! az #:package irányelvek után):

    using System.CommandLine;
    using System.CommandLine.Parsing;
    
  3. Adja meg a késleltetési beállítást és az üzenetek argumentumát. Adja hozzá a következő kódot a CommandLine.Option parancssori beállítás és CommandLine.Argument az argumentum megjelenítéséhez:

    Option<int> delayOption = new("--delay")
    {
        Description = "Delay between lines, specified as milliseconds.",
        DefaultValueFactory = parseResult => 100
    };
    
    Argument<string[]> messagesArgument = new("Messages")
    {
        Description = "Text to render."
    };
    

    A parancssori alkalmazásokban a beállítások általában (dupla kötőjellel -- ) kezdődnek, és argumentumokat fogadnak el. A --delay beállítás egy egész szám argumentumot fogad el, amely ezredmásodpercben határozza meg a késést. Ez messagesArgument határozza meg, hogy a beállítások után fennmaradó jogkivonatok hogyan lesznek szövegként elemezve. Minden jogkivonat külön sztringgé válik a tömbben, de a szöveg idézhető úgy, hogy több szót is belefoglaljon egy jogkivonatba. Például "This is one message" egyetlen jogkivonat lesz, míg This is four tokens négy különálló jogkivonat lesz.

    Az előző kód határozza meg a beállítás argumentumtípusát --delay , és hogy az argumentumok értéktömbök string . Ez az alkalmazás csak egy paranccsal rendelkezik, ezért a gyökérparancsot kell használnia.

  4. Hozzon létre egy gyökérparancsot, és konfigurálja a beállítással és az argumentummal. Adja hozzá az argumentumot és a lehetőséget a gyökérparancshoz:

    RootCommand rootCommand = new("Ascii Art file-based program sample");
    
    rootCommand.Options.Add(delayOption);
    rootCommand.Arguments.Add(messagesArgument);
    
  5. Adja hozzá a kódot a parancssori argumentumok elemzéséhez és a hibák kezeléséhez. Ez a kód ellenőrzi a parancssori argumentumokat, és elemzi az argumentumokat az System.CommandLine.ParseResult objektumban:

    ParseResult result = rootCommand.Parse(args);
    foreach (ParseError parseError in result.Errors)
    {
        Console.Error.WriteLine(parseError.Message);
    }
    if (result.Errors.Count > 0)
    {
        return 1;
    }
    

Az előző kód ellenőrzi az összes parancssori argumentumot. Ha az ellenőrzés sikertelen, a rendszer hibákat ír a konzolra, és az alkalmazás kilép.

Elemezett parancssori eredmények használata

Most fejezze be az alkalmazást az elemzési beállítások használatához, és írja meg a kimenetet. Először definiáljon egy rekordot az elemzési beállítások tárolásához. A fájlalapú alkalmazások tartalmazhatnak típusdeklarációkat, például rekordokat és osztályokat. Az összes legfelső szintű utasítás és helyi függvény után kell lenniük.

  1. Adjon hozzá egy deklarációt record az üzenetek és a késleltetési beállítás értékének tárolásához:

    public record AsciiMessageOptions(string[] Messages, int Delay);
    
  2. Adja hozzá a következő helyi függvényt a rekorddeklaráció előtt. Ez a metódus a parancssori argumentumokat és a standard bemenetet is kezeli, és egy új rekordpéldányt ad vissza:

    async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
    {
        int delay = result.GetValue(delayOption);
        List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()];
    
        if (messages.Count == 0)
        {
            while (Console.ReadLine() is string line && line.Length > 0)
            {
                Colorful.Console.WriteAscii(line);
                await Task.Delay(delay);
            }
        }
        return new([.. messages], delay);
    }
    
  3. Hozzon létre egy helyi függvényt az ASCII-kép megírásához a megadott késleltetéssel. Ez a függvény minden üzenetet a rekordba ír, az egyes üzenetek között megadott késleltetéssel:

    async Task WriteAsciiArt(AsciiMessageOptions options)
    {
        foreach (string message in options.Messages)
        {
            Colorful.Console.WriteAscii(message);
            await Task.Delay(options.Delay);
        }
    }
    
  4. Cserélje le a if korábban írt záradékot a parancssori argumentumokat feldolgozó és a kimenetet feldolgozó következő kódra:

    var parsedArgs = await ProcessParseResults(result);
    
    await WriteAsciiArt(parsedArgs);
    return 0;
    

Létrehozott egy típust record , amely strukturálja az elemezett parancssori beállításokat és argumentumokat. Az új helyi függvények létrehozzák a rekord egy példányát, és a rekord használatával megírják az ASCII art kimenetét.

A végleges alkalmazás tesztelése

Tesztelje az alkalmazást több különböző parancs futtatásával. Ha problémát tapasztal, az alábbi minta összehasonlítható a létrehozottval:

#!/usr/local/share/dotnet/dotnet run

#:package Colorful.Console@1.2.15
#:package System.CommandLine@2.0.0

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

Option<int> delayOption = new("--delay")
{
    Description = "Delay between lines, specified as milliseconds.",
    DefaultValueFactory = parseResult => 100
};

Argument<string[]> messagesArgument = new("Messages")
{
    Description = "Text to render."
};

RootCommand rootCommand = new("Ascii Art file-based program sample");

rootCommand.Options.Add(delayOption);
rootCommand.Arguments.Add(messagesArgument);

ParseResult result = rootCommand.Parse(args);
foreach (ParseError parseError in result.Errors)
{
    Console.Error.WriteLine(parseError.Message);
}
if (result.Errors.Count > 0)
{
    return 1;
}

var parsedArgs = await ProcessParseResults(result);

await WriteAsciiArt(parsedArgs);
return 0;

async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
{
    int delay = result.GetValue(delayOption);
    List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()];

    if (messages.Count == 0)
    {
        while (Console.ReadLine() is string line && line.Length > 0)
        {
            // <WriteAscii>
            Colorful.Console.WriteAscii(line);
            // </WriteAscii>
            await Task.Delay(delay);
        }
    }
    return new([.. messages], delay);
}

async Task WriteAsciiArt(AsciiMessageOptions options)
{
    foreach (string message in options.Messages)
    {
        Colorful.Console.WriteAscii(message);
        await Task.Delay(options.Delay);
    }
}

public record AsciiMessageOptions(string[] Messages, int Delay);

Ebben az oktatóanyagban elsajátította egy fájlalapú program összeállítását, amelyben a programot egyetlen C#-fájlban hozza létre. Ezek a programok nem használnak projektfájlt, és használhatják a #! unix rendszerekre vonatkozó irányelveket. A tanulók az online oktatóanyagok kipróbálása és a nagyobb projektalapú alkalmazások létrehozása előtt hozhatják létre ezeket a programokat. A fájlalapú alkalmazások a parancssori segédprogramok számára is nagyszerű platformot jelentenek.