CLI фреймворк для C# (.NET): System.CommandLine и Spectre.Console

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

CLI фреймворк для C# (.NET): System.CommandLine и Spectre.Console

Создание качественных консольных приложений (CLI) на C# — задача, которая требует не только обработки аргументов командной строки, но и удобного представления данных, поддержки подкоманд, валидации и интерактивности. В экосистеме .NET для этого существуют два мощных инструмента: официальный System.CommandLine от Microsoft и универсальная библиотека Spectre.Console. В этой статье мы подробно разберём их возможности, покажем примеры использования и сравним подходы.

1. System.CommandLine: официальный парсер от Microsoft

System.CommandLine — это библиотека с открытым исходным кодом, которая предоставляет декларативный способ определения команд, аргументов, опций и обработчиков. Она входит в состав .NET SDK (начиная с .NET 6) и доступна как NuGet-пакет.

Основные возможности

  • Декларативное описание структуры команд с помощью атрибутов или fluent API.
  • Автоматическая генерация справки (--help).
  • Поддержка вложенных команд (subcommands) и псевдонимов.
  • Валидация аргументов и опций (типы, диапазоны, обязательность).
  • Интеграция с DI-контейнерами и middleware.

Пример: простое приложение с двумя командами

Создадим консольное приложение, которое поддерживает команды greet и calc.

using System.CommandLine;

var rootCommand = new RootCommand("Многофункциональное CLI-приложение");

// Команда greet
var greetCommand = new Command("greet", "Приветствие пользователя");
var nameOption = new Option<string>(
    "--name",
    () => "мир",
    "Имя для приветствия");
greetCommand.AddOption(nameOption);

greetCommand.SetHandler((string name) =>
{
    Console.WriteLine($"Привет, {name}!");
}, nameOption);

// Команда calc
var calcCommand = new Command("calc", "Простой калькулятор");
var aArgument = new Argument<int>("a", "Первое число");
var bArgument = new Argument<int>("b", "Второе число");
var operationOption = new Option<string>(
    "--operation",
    () => "add",
    "Операция: add, sub, mul, div");
calcCommand.AddArgument(aArgument);
calcCommand.AddArgument(bArgument);
calcCommand.AddOption(operationOption);

calcCommand.SetHandler((int a, int b, string op) =>
{
    var result = op switch
    {
        "add" => a + b,
        "sub" => a - b,
        "mul" => a * b,
        "div" => b != 0 ? a / b : throw new DivideByZeroException(),
        _ => throw new ArgumentException("Неизвестная операция")
    };
    Console.WriteLine($"Результат: {result}");
}, aArgument, bArgument, operationOption);

rootCommand.AddCommand(greetCommand);
rootCommand.AddCommand(calcCommand);

return await rootCommand.InvokeAsync(args);

Запуск приложения:

dotnet run -- greet --name "PythonLib"
dotnet run -- calc 10 5 --operation mul

2. Spectre.Console: красота и интерактивность

Spectre.Console — это библиотека для создания красивых консольных интерфейсов. Она не заменяет парсер аргументов, но отлично дополняет его: цветной вывод, таблицы, прогресс-бары, интерактивные меню и даже рисование в консоли.

Основные возможности

  • Цветной и форматированный вывод с поддержкой Markdown.
  • Таблицы, диаграммы, календари.
  • Интерактивные компоненты: выбор из списка, ввод текста, подтверждение.
  • Анимация (спиннеры, прогресс-бары).
  • Рисование рамок, панелей и колонок.

Пример: интерактивное меню и таблица

Покажем, как создать меню выбора и вывести данные в виде таблицы.

using Spectre.Console;

// Интерактивное меню
var choice = AnsiConsole.Prompt(
    new SelectionPrompt<string>()
        .Title("Выберите действие:")
        .PageSize(5)
        .AddChoices(new[] {
            "Показать информацию",
            "Вывести таблицу",
            "Выйти"
        }));

if (choice == "Показать информацию")
{
    // Цветной вывод с рамкой
    var panel = new Panel(new Markup("[bold yellow]Добро пожаловать в PythonLib![/]"))
    {
        Border = BoxBorder.Rounded,
        Header = new PanelHeader("Информация")
    };
    AnsiConsole.Write(panel);                    

Рекомендаций