Недавно я наткнулся на реализацию синтаксического анализа командной строки FubuCore, которая мне действительно нравится по следующим причинам:
- он прост в использовании - хотя я не смог найти документацию для него, решение FubuCore также предоставляет проект, содержащий хороший набор модульных тестов, которые говорят о функциональности больше, чем любая документация
- у него приятный объектно-ориентированный дизайн, нет повторения кода или других подобных вещей, которые я имел в своих приложениях для разбора командной строки
- это декларативно: вы в основном пишете классы для команд и наборов параметров и украшаете их атрибутами, чтобы установить различные опции (например, имя, описание, обязательный / необязательный)
- библиотека даже печатает хороший график использования, основанный на этих определениях
Ниже приведен простой пример того, как это использовать. Чтобы проиллюстрировать использование, я написал простую утилиту, которая имеет две команды: - add (добавляет объект в список - объект состоит из имени (строки), значения (int) и логического флага) - list (lists все добавленные в данный момент объекты)
Прежде всего, я написал класс Command для команды 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;
}
}
Эта команда принимает экземпляр CommandInput в качестве параметра, поэтому я определю это следующим образом:
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; }
}
Следующая команда - это список, который реализован следующим образом:
[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;
}
}
Команда 'list' не принимает параметров, поэтому для этого я определил класс NullInput:
public class NullInput { }
Теперь осталось только подключить это в методе Main (), например так:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
Программа работает должным образом, выводит подсказки о правильном использовании в случае, если какие-либо команды недопустимы:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
И пример использования для команды «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
-------------------------------------