libargument

    • Beta
    • Open Source

    Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von AliveDevil.

      libargument

      libargument
      Die einfache Bibliothek zum entwickeln von .NET Anwendungen, die auf Basis der Befehlszeile bestimme Aktionen ausführt.

      Achtung Diese Bibliothek ist ein Work in Progress. Erwarte nicht, dass sie fehlerfrei läuft. Ich habe sie nur schon veröffentlicht, weil ich das Feedback dazu haben möchte und die Bibliothek grundsätzlich funktioniert.

      Verwendete IDE
      Visual Studio 2013

      Sprache
      C#

      Voraussetzungen
      .NET 3.5 Client Profile oder .NET 4.0 Client Profile

      Klassendiagramm


      Beispiel

      VB.NET-Quellcode

      1. Dim parser As New libargument.Parser(Of ParserTestController)("parameter")
      2. parser.Tokenize()
      3. parser.Match() ' oder parser.Match(Of Type)() wenn ein Rückgabewert erwartet wird.
      4. Class ParserTestController
      5. Inherits libargument.Controller
      6. <libargument.Attributes.ParseAttribute()> _
      7. Public Sub Test(<libargument.Attributes.KeyAttribute("test")> testParameter As Boolean)
      8. Console.WriteLine("Wundervolle Funktion.")
      9. End Sub
      10. End Class

      C#-Quellcode

      1. var parser = new libargument.Parser<ParserTestController>("parameter");
      2. parser.Tokenize();
      3. parser.Match(); // oder parser.Match<T>() wenn ein Rückgabewert erwartet wird.
      4. class ParserTestController : libargument.Controller
      5. {
      6. [libargument.Attributes.ParseAttribute]
      7. public void Test([libargument.Attributes.KeyAttribute("test")] bool testParameter)
      8. {
      9. Console.WriteLine("Wundervolle Funktion.");
      10. }
      11. }


      Bekannte Fehler
      • /help funktioniert nicht


      ToDo
      • Lokalisierungen
      • Es fehlen noch drei Exceptions, die keine Aussagekraft haben.
      • Hilfe-Generator einbauen


      Links
      Aktuelle Codebase
      Aktuelle Binaries
      Releases
      Changelog
      Direktlink zum Release v0.1.0.0-pre Veraltet
      Direktlink zum Release v0.2.2-pre
      Spiegel des libargument Release v0.1.0.0-pre Veraltet
      Spiegel des libargument Release v0.2.1-pre Veraltet
      Spiegel des libargument Release v0.2.2-pre

      Lizenz
      GPLv2

      Sonstiges
      Kritik, Verbesserungsvorschläge und ähnliches in diesen Thread oder auf GitHub in die Issues. Ich werde alles lesen und so gut es geht beantworten. Beachtet aber, dass ihr im GitHub-Repository auf Englisch schreiben solltet.
      Diskussionen auf GitHub werde ich, sofern beantwortet und übernommen, als Posting in diesen Thread werfen, sodass ihr immer auf dem neusten Stand seid.

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „AliveDevil“ ()

      Ich habe ein wenig an der Bibliothek geschrieben.
      Einige Stabilitätsverbesserungen und neue Funktionen habe ich darin eingebaut.
      Mit der Version v0.2.0 wurde folgendes getan:
      • Dokumentation erweitert
      • Switch-Typ eingebaut (es wird kein Boolean für einfache Parameter gebraucht)
      • Ein Attribut zum Überschreiben des Anwendungsnamen wurde eingebaut (ohne Funktion)
      • Viele Fehler der Bibliothek wurden behoben

      Mit der Version v0.2.1 wurden folgendes geändert:
      • Options-Attribut eingefügt, sodass der Controller selbst Variablen definieren kann
      • Es wird eine NotResolved-Ausnahme geworfen, wenn Argumente nicht zugeordnet wurden
      • Die NotResolved-Ausnahme kann durch Überschreiben der Eigenschaft SkipUnresolvedArguments deaktiviert werden

      Mit der Version v0.2.2 wurde folgendes behoben:
      • Der Parser hat Parameter falsch angenommen, wodurch er beim Ausführen mit einer Ausnahme beendet hat.
      • Changelog ist wieder korrekt.


      Das Release v0.2.2-pre kann hier heruntergeladen werden.

      Anregungen zur Bibliothek wären sehr nett.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „AliveDevil“ ()

      Du kannst mit der Bibliothek automatisiert Befehlszeilenparameter auslesen und daraufhin Aktionen ausführen lassen.
      Nimm die Beispielsweise eine Anwendung, die drei verschiedene Dinge durchführt: Erstellen, Löschen, Auflisten.
      Der geneigte Entwickler würde sich jetzt eine Schleife bauen und drauflos entwickeln.

      C#-Quellcode

      1. public static void Main(string[] args)
      2. {
      3. for (int i = 0; i < args.Length; i++)
      4. {
      5. var arg = args[i].ToLowerInvariant();
      6. switch (arg)
      7. {
      8. case "create":
      9. if (args.Length > 1)
      10. {
      11. var fi = new FileInfo(args[1]);
      12. using (var stream = fi.Create())
      13. // irgendetwas mit dem Stream anfangen.
      14. }
      15. break;
      16. case "delete":
      17. if (args.Length > 1)
      18. {
      19. var fi = new FileInfo(args[1]);
      20. if (fi.Exists)
      21. fi.Delete()
      22. }
      23. break;
      24. case "list":
      25. if (args.Length > 1)
      26. {
      27. var di = new DirectoryInfo(args[1]);
      28. if (di.Exists)
      29. foreach (var file in di.EnumerateFiles())
      30. Console.WriteLine("File: {0}", file.Name);
      31. }
      32. break;
      33. }
      34. }
      35. }

      Aufrufen:

      Quellcode

      1. App.exe create file.exe
      2. App.exe delete file.exe
      3. App.exe list C:\Ordner


      Du merkst selbst, dass das nicht wirklich zielführend ist.
      Mit der Bibliothek würdest du soetwas machen:

      C#-Quellcode

      1. using System.IO;
      2. using libargument;
      3. using libargument.Attributes;
      4. public class SimpleController : Controller
      5. {
      6. [Parse]
      7. public void CreateFile([Key("create")] Switch create, [Key("file")] String file, [Key("overwrite")] Boolean overwrite = false]
      8. {
      9. var fi = new FileInfo(file);
      10. if (fi.Exists && overwrite)
      11. fi.Delete();
      12. else
      13. throw new FileExistsException();
      14. using (var stream = fi.Create())
      15. // irgendetwas darein schreiben
      16. }
      17. [Parse]
      18. public void DeleteFile([Key("delete")] Switch delete, [Key("file")] String file)
      19. {
      20. var fi = new FileInfo(file);
      21. if (fi.Exists)
      22. fi.Delete();
      23. }
      24. [Parse]
      25. public void ListFiles([Key("list")] Switch list, [Key("directory")] String directory)
      26. {
      27. var di = new DirectoryInfo(directory);
      28. if (di.Exists)
      29. foreach (var file in di.EnumerateFiles())
      30. Console.WriteLine("File: {0}", file.Name);
      31. }
      32. }
      33. public static void Main(string[] args)
      34. {
      35. // damit gehts auf jeden fall. String.Join(" ", args) funktioniert leider nicht.
      36. var parser = new Parser<SimpleController>(Environment.CommandLine.Replace(Environment.GetCommandLineArgs()[0], "").Trim());
      37. parser.Tokenize();
      38. parser.Match();
      39. }

      Aufrufen:

      Quellcode

      1. App.exe /create /file="Test.exe"
      2. App.exe /create /file="Test.exe" /overwrite=true
      3. App.exe /delete /file="Test.exe"
      4. App.exe /list /directory="C:\Irgendein\Verzeichnis"


      Zudem wird später noch eine automatisierte Hilfe angezeigt. (derzeit nicht eingebaut)
      Ein sehr interessanter Ansatz und durchaus flexibel, wenn man nur spezielle Parameterkombinationen erlaubt!

      Ich hatte mal an folgenden Ansatz gedacht:
      Spoiler anzeigen

      C#-Quellcode

      1. class Arguments
      2. {
      3. [ArgumentSwitch("n", "network", true)] // "-n" bzw. alias "--network" (bool sagt, ob optional)
      4. public bool SomeSwitch { get; set; }
      5. [ArgumentValue("f", "file", false)]
      6. public string SomePath { get; set; }
      7. private static Arguments _current;
      8. public static Arguments Current { get { return _current ?? (_current = new Arguments()); } }
      9. private Arguments()
      10. { }
      11. }
      12. // ...
      13. public static void Main(string[] args)
      14. {
      15. ArgumentHandler.Fetch(Arguments.Current); // fetcht die parameter mit den propertys der Klasseninstanz
      16. bool isValid = ArgumentHandler.CheckValidity(); // prüft, ob required-parameter übergeben wurden etc
      17. if(isValid)
      18. {
      19. if(Arguments.Current.SomeSwitch)
      20. Console.WriteLine("Using Network mode");
      21. Console.WriteLine("Output file: " + Arguments.Current.SomePath);
      22. }
      23. }


      Vielleicht inspiriert dich das ja etwas.
      Von meinem iPhone gesendet
      Ein ähnliches Verhalten ist bereits implementiert .. teilweise (ich weiß nurnicht, ob es funktioniert)

      C#-Quellcode

      1. public class ArgumentTest
      2. {
      3. [Option]
      4. public Switch SomeSwitch;
      5. [Option]
      6. public string SomeValue;
      7. [Parse]
      8. public void CatchAll()
      9. {
      10. DoSomething();
      11. }
      12. }

      Das parser.Match() bzw. parser.Match<T>() kann dann mit einem Try-Catch abgefangen werden (wird 100%ig geworfen, wenn mehr als eine Parse-Methode vorhanden ist) oder alternativ einen bool zurückgeben, ob alles korrekt ist.
      also:

      C#-Quellcode

      1. try
      2. {
      3. parser.Match();
      4. }
      5. catch (IrgendeineException ex)
      6. {
      7. // Invalid.
      8. }

      oder

      C#-Quellcode

      1. if (parser.Match<bool>())
      2. {
      3. // Valid.
      4. }