Di recente mi sono imbattuto in The FubuCore Command line analizzando l'implementazione, mi piace davvero, i motivi sono:
- è facile da usare - anche se non sono riuscito a trovare una documentazione per esso, la soluzione FubuCore fornisce anche un progetto contenente un bel set di Test unit che parlano più delle funzionalità di quanto qualsiasi documentazione potrebbe
- ha un bel design orientato agli oggetti, nessuna ripetizione di codice o altre cose simili che avevo nella mia riga di comando per l'analisi delle app
- è dichiarativo: fondamentalmente scrivi le classi per i Comandi e le serie di parametri e le decori con gli attributi per impostare varie opzioni (es. nome, descrizione, obbligatorio / opzionale)
- la biblioteca stampa anche un bel grafico di utilizzo, basato su queste definizioni
Di seguito è riportato un semplice esempio su come utilizzare questo. Per illustrare l'utilizzo, ho scritto una semplice utility che ha due comandi: - aggiungi (aggiunge un oggetto a un elenco - un oggetto è composto da un nome (stringa), valore (int) e un flag booleano) - elenco (elenchi tutti gli oggetti attualmente aggiunti)
Prima di tutto, ho scritto una classe Command per il comando '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;
}
}
Questo comando accetta un'istanza CommandInput come parametro, quindi lo definisco dopo:
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; }
}
Il comando successivo è 'list', che viene implementato come segue:
[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;
}
}
Il comando 'list' non accetta parametri, quindi ho definito una classe NullInput per questo:
public class NullInput { }
Ora non resta che collegarlo nel metodo Main (), in questo modo:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
Il programma funziona come previsto, stampando suggerimenti sull'uso corretto in caso di comandi non validi:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
E un esempio di utilizzo per il comando 'aggiungi':
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
-------------------------------------