Recentemente, me deparei com a implementação de análise de linha de comando FubuCore que eu realmente gosto, as razões são:
- é fácil de usar - embora eu não tenha conseguido encontrar uma documentação para isso, a solução FubuCore também fornece um projeto contendo um bom conjunto de testes de unidade que falam mais sobre a funcionalidade do que qualquer documentação poderia
- ele possui um design orientado a objetos, sem repetição de código ou outras coisas que eu costumava ter em meus aplicativos de análise de linha de comando
- é declarativo: você basicamente escreve classes para os comandos e conjuntos de parâmetros e os decora com atributos para definir várias opções (por exemplo, nome, descrição, obrigatório / opcional)
- a biblioteca até imprime um bom gráfico de uso, com base nessas definições
Abaixo está um exemplo simples de como usar isso. Para ilustrar o uso, escrevi um utilitário simples que possui dois comandos: - add (adiciona um objeto a uma lista - um objeto consiste em um nome (string), valor (int) e um sinalizador booleano) - list (lists todos os objetos adicionados atualmente)
Primeiro de tudo, escrevi uma classe Command para o 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;
}
}
Este comando usa uma instância CommandInput como parâmetro, então eu defino isso a seguir:
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; }
}
O próximo comando é 'list', que é implementado da seguinte maneira:
[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;
}
}
O comando 'list' não possui parâmetros, então eu defini uma classe NullInput para isso:
public class NullInput { }
Tudo o que resta agora é conectar isso no método Main (), assim:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
O programa funciona conforme o esperado, imprimindo dicas sobre o uso correto, caso algum comando seja inválido:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
E um exemplo de uso para o comando 'add':
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
-------------------------------------