Ostatnio natknąłem się na implementację parsowania wiersza poleceń FubuCore. Bardzo mi się podoba, ponieważ:
- jest łatwy w użyciu - chociaż nie mogłem znaleźć dokumentacji na jego temat, rozwiązanie FubuCore zapewnia również projekt zawierający ładny zestaw testów jednostkowych, które mówią więcej o funkcjonalności niż jakakolwiek dokumentacja
- ma ładny obiektowy design, bez powtarzania kodu lub innych podobnych rzeczy, które miałem w mojej aplikacji do analizowania wiersza poleceń
- jest deklaratywny: w zasadzie piszesz klasy dla poleceń i zestawów parametrów i dekorujesz je atrybutami, aby ustawić różne opcje (np. nazwa, opis, obowiązkowe / opcjonalne)
- biblioteka drukuje nawet ładny wykres użytkowania na podstawie tych definicji
Poniżej znajduje się prosty przykład, jak z tego korzystać. Aby zilustrować użycie, napisałem proste narzędzie, które ma dwa polecenia: - dodaj (dodaje obiekt do listy - obiekt składa się z nazwy (łańcucha), wartości (int) i flagi boolowskiej) - listy (list wszystkie aktualnie dodane obiekty)
Przede wszystkim napisałem klasę Command dla polecenia „add”:
[Usage("add", "Adds an object to the list")]
[CommandDescription("Add object", Name = "add")]
public class AddCommand : FubuCommand<CommandInput>
{
public override bool Execute(CommandInput input)
{
State.Objects.Add(input); // add the new object to an in-memory collection
return true;
}
}
To polecenie przyjmuje instancję CommandInput jako parametr, więc definiuję następną:
public class CommandInput
{
[RequiredUsage("add"), Description("The name of the object to add")]
public string ObjectName { get; set; }
[ValidUsage("add")]
[Description("The value of the object to add")]
public int ObjectValue { get; set; }
[Description("Multiply the value by -1")]
[ValidUsage("add")]
[FlagAlias("nv")]
public bool NegateValueFlag { get; set; }
}
Następnym poleceniem jest „lista”, które jest realizowane w następujący sposób:
[Usage("list", "List the objects we have so far")]
[CommandDescription("List objects", Name = "list")]
public class ListCommand : FubuCommand<NullInput>
{
public override bool Execute(NullInput input)
{
State.Objects.ForEach(Console.WriteLine);
return false;
}
}
Polecenie „list” nie przyjmuje parametrów, więc zdefiniowałem dla tego klasę NullInput:
public class NullInput { }
Teraz pozostaje tylko załączyć to w metodzie Main (), tak jak to:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
Program działa zgodnie z oczekiwaniami, drukując wskazówki dotyczące prawidłowego użycia w przypadku, gdy jakiekolwiek polecenia są nieprawidłowe:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
I przykładowe użycie polecenia „dodaj”:
Usages for 'add' (Add object)
add <objectname> [-nv]
-------------------------------------------------
Arguments
-------------------------------------------------
objectname -> The name of the object to add
objectvalue -> The value of the object to add
-------------------------------------------------
-------------------------------------
Flags
-------------------------------------
[-nv] -> Multiply the value by -1
-------------------------------------