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 amelyeket megfelelő projektfájl (*.csproj) nélkül hozhat létre és futtathat. 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 fájlalapú alkalmazásokat futtathat (shebang) #! használatával . Ebben az útmutatóban Ön:

  • Fájlalapú alkalmazás létrehozása.
  • Unix shebang (#!) támogatás hozzáadása.
  • Parancssori argumentumok olvasása.
  • Standard bemenet kezelése.
  • Írj ASCII rajz kimenetet.
  • Parancssori argumentumok feldolgozása.
  • Elemezett parancssori eredmények használata.
  • Tesztelje a végleges alkalmazást.

Olyan fájlalapú alkalmazást hozhat létre, amely ASCII-művészetként ír szöveget. Az alkalmazás egyetlen fájlban található, NuGet-csomagokat használ, és alapvető funkciókat valósít meg.

Előfeltételek

Fájlalapú alkalmazás 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 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 AsciiArt.cs ellenőrizheti. A gazdagép ezúttal azt határozza meg, hogy a végrehajtható fájl aktuális-e, dotnet és anélkül futtatja a végrehajtható fájlt, hogy újra létrejön. Nem látja az építési kimenetet.

Az előző lépések azt mutatják, hogy a fájlalapú alkalmazások nem szkriptfájlok. Ezek olyan C#-forrásfájlok, amelyeket a dotnet gazdagép egy ideiglenes mappában létrehozott projektfájl használatával hoz létre. 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 szerkeszti a forrásfájlt, a dotnet gazdagép még 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 írnia ő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 egy fájlalapú alkalmazásban, 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ú alkalmazás túl nagy egy fájlhoz, konvertálhatja projektalapú programmá, é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 a 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 .

A Unixon közvetlenül a forrásfájlnév használatával hajthat végre fájlalapú alkalmazásokat. 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
    

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 közvetlenül futtathatja a programot:

./AsciiArt.cs

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

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 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:

  • Az előre definiált változó args átadja a parancssori argumentumokat a programnak. A args változó sztringek tömbje: string[]. Ha a hossz args 0, 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 darab szóköz karakter.
  • Console.WriteLine A sztringet a standard kimeneti konzolra írja, majd egy új sort.

Standard bemenet kezelése

Az előző kód helyesen kezeli a parancssori argumentumokat. Adja hozzá a kódot a standard bemenetről (stdin) történő adatolvasás 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 helyesen formázzák azokat, amikor az ASCII művészet használatának funkcióját hozzáadja.

  3. Futtassa újra a programot.

    Bash használatával:

    cat input.txt | dotnet AsciiArt.cs
    

    Vagy a PowerShell használatával:

    Get-Content input.txt | dotnet AsciiArt.cs
    

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

ASCII-rajzkimenet írása

Ezután vegyen fel egy olyan csomagot, amely támogatja az ASCII-művészetet, a Colorful.Console-t. Ha csomagokat szeretne hozzáadni egy fájlalapú alkalmazáshoz, 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. Változtassa meg a Console.WriteLine felhívó sorokat, hogy inkább a Colorful.Console.WriteAscii metódust használják.

    Colorful.Console.WriteAscii(line);
    
  3. Futtassa a programot. Az ASCII art kimenete a visszhangzott szöveg helyett jelenik meg.

Folyamatparancs beállításai

Ezután adja hozzá a 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. Idézz több szót, amelyeket egy sorba 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ók mindkét argumentumot használhatják együtt.

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ó funkciókat biztosít a parancsok, alparancsok, beállítások és argumentumok kezeléséhez. A parancssori bemenet elemzése helyett az alkalmazás működésére ö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 (a #! és #: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, hogy létrehozza a CommandLine.Option és CommandLine.Argument objektumokat, amelyek a parancssori beállítást és argumentumot képviselik.

    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ó tokenek 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 --delay beállítás argumentumtípusát, valamint azt is, hogy az argumentumok egy string típusú értékekből álló tömb. 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 app 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 az elemzett argumentumokat az System.CommandLine.ParseResult objektumban tárolja.

    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, az alkalmazás hibákat ír a konzolra, é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 következő kódra, amely feldolgozza a parancssori argumentumokat, és írja a kimenetet:

    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/bin/env dotnet

#: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 app 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 megtanult egy fájlalapú alkalmazást létrehozni, 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.