29

Создание CLI-приложений при помощи System.CommandLine в .NET

Серия Технические статьи

В .NET уже несколько лет существует библиотека System.CommandLine, позволяющая быстро создавать CLI-приложения. Несмотря на то, что библиотека ещё в стадии beta, её активно используют и сами разработчики Microsoft, например, в утилите dotnet из пакета .NET SDK.

Преимущества этой библиотеки в том, что она позволяет сосредоточиться на разработке полезного функционала приложения и не тратить время на создание парсера команд, опций и аргументов, а также имеет широкие возможности для кастомизации.

Реализация простого CLI-приложения

Библиотека поддерживает следующие виды токенов:

Опции и аргументы определяются совместно через обобщённый тип Option<T>:

Полностью исходный код можно найти в нашем GitLab-репозитории.

Subcommand и command отличаются тем, что subcommand определяет группу команд, а command определяет непосредственно действие, выполняемое командой.

Определим для начала команду sum:

Разделение на команды и группы команд очень условное, т.к. с точки зрения C# оба вида определяются через класс Command. Также нам ничто не мешает определить действие и для группы команд:

Помимо примитивных типов, библиотека также поддерживает массивы, списки, FileInfo, DirectoryInfo и другие. Полный список можно узнать, заглянув в документацию. Если есть необходимость привязать опции к кастомному типу, то можно воспользоваться встроенным механизмом привязки через тип BinderBase<T>. Определим операцию вычитания, используя этот способ:

Тогда определение хендлера для команды вычитания будет выглядеть следующим образом:

Осталось определить Root command через одноимённый класс RootCommand :

Теперь можно собрать приложение и проверить работу:

Внедрение зависимостей

Жизненный цикл CLI-приложения выглядит следующим образом:

  1. Вызывается некоторая команда.

  2. Запускается процесс.

  3. Происходит обработка данных, возвращается результат.

  4. Процесс завершается.

Классические контейнеры зависимостей не рекомендуется использовать, поскольку зависимости одной команды могут быть совершенно не нужны для другой команды, а инициализация всех зависимостей может увеличить время запуска CLI-приложения. Вместо этого можно воспользоваться механизмом внедрения зависимостей для конкретного обработчика. Для этого снова понадобится класс BinderBase<T>. Определим новый класс ResultWriter, который будет записывать результат математической операции в файл:

Теперь создадим класс ResultWriterBinder. Этот класс инкапсулирует экземпляр ResultWriter:

=> _resultWriter;

Теперь определим операцию умножения и внедрим туда экземпляр ResultWriter:

Такой подход позволяет внедрять зависимости в обработчики команд независимо друг от друга.

Кастомизация вывода

Справка генерируется автоматически из описаний, которые использовались при инициализации опций и команд. Например, команда cli-app math sum -h отобразит следующее:

При желании можно заменить любой раздел справки, например, Description или создать новый. Добавим новую строку с текстом «This is a new section» в начало справки:

Тогда вывод станет следующим:

Если требуется улучшить внешний вид вывода данных в целом, то сделать это можно, например, написав кастомный способ отображения при помощи методов и свойств класса Console, таких как SetCursorPosition, ForegroundColor, BackgroundColor и т.д. Либо воспользоваться 3rd-party библиотеками:

1. ShellProgressBar. Простая библиотека для отображения прогресса в командном окне.

2. Spectre.Console. Мощная библиотека для создания красивых консольных приложений, которая имеет множество компонентов, упрощающих создание интерфейса. Кстати, обложка для статьи была сделана с помощью этой библиотеки.

3. ConsoleGUI. Позволяет создавать полноценный GUI на основе консоли. Судя по всему, автор вдохновлялся WPF, так как в ней содержатся привычные для этого фреймворка компоненты: TextBox, CheckBox, DataGrid, DockPanel и другие.

Заключение

Библиотека System.CommandLine является полезным инструментом для создания CLI-приложений. Она даёт разработчикам гибкий инструментарий для работы командами и опциями, что позволяет сократить время разработки и создать удобный и функциональный пользовательский интерфейс.

Лига программистов

2.1K постов11.9K подписчик

Правила сообщества

- Будьте взаимовежливы, аргументируйте критику

- Приветствуются любые посты по тематике программирования

- Если ваш пост содержит ссылки на внешние ресурсы - он должен быть самодостаточным. Вариации на тему "далее читайте в моей телеге" будут удаляться из сообщества

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества