عنوان:

‫انتشار نسخهٔ پایدار System.CommandLine توسط مایکروسافت


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۸/۲۴ ۱۰:۵۷
آدرس: www.dntips.ir
در ۱۱ نوامبر ۲۰۲۵ (چند روز پیش)، مایکروسافت بالاخره نسخهٔ پایدار و GA (General Availability) بستهٔ System.CommandLine 2.0.0 را منتشر کرد. این بسته بعد از حدود ۴ سال ماندن در مرحلهٔ بتا و RC، حالا به‌صورت کاملاً پایدار و آمادهٔ استفاده در پروژه‌های تولیدی در دسترس است.
System.CommandLine بهترین و رسمی‌ترین راه برای ساخت ابزارهای خط فرمان حرفه‌ای در اکوسیستم .NET است و قابلیت‌هایی مثل:
  • پارسینگ خودکار آرگومان‌ها و آپشن‌ها
  • تولید خودکار --help و --version
  • اعتبارسنجی ورودی‌ها
  • پیشنهاد تکمیل دستورات (Suggestion)
  • پشتیبانی از Response File (@file)
  • میان‌افزارها (Middleware)
  • ادغام کامل با Microsoft.Extensions.Hosting و Dependency Injection
  • قابلیت انتشار به‌صورت dotnet tool
  • محلی‌سازی متن کمک
را به‌صورت آماده و بدون نیاز به کد اضافی ارائه می‌دهد.

نصب بسته
dotnet add package System.CommandLine --version 2.0.0
(در زمان نوشتن این مقاله، این آخرین نسخهٔ پایدار است)

پروژهٔ سادهٔ Console در .NET 10
یک پروژهٔ کنسولی معمولی بسازید:
dotnet new console -n DemoCli
cd DemoCli
dotnet add package System.CommandLine
فایل DemoCli.csproj را به این شکل تغییر دهید تا به‌صورت dotnet tool منتشر شود:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>

    <!-- این بخش باعث می‌شود بتوانید با dotnet pack → dotnet tool install -g demo اجرا کنید -->
    <PackAsTool>true</PackAsTool>
    <ToolCommandName>demo</ToolCommandName> <!-- نام دستوری که در ترمینال استفاده می‌شود -->
    <PackageId>DemoCli</PackageId>
    <Version>1.0.0</Version>
  </PropertyGroup>

</Project>

مثال عملی: دستورgreet
هدف:
demo greet Diane 3 → سه بار Hello, Diane! چاپ کند
demo greet Jack 5 -u → پنج بار HELLO, JACK! چاپ کند
نسخهٔ تمیز و توصیه‌شده (با Binding خودکار)
using System.CommandLine;
using System.CommandLine.Invocation;

var nameArg = new Argument<string>("name", "نام شخص برای سلام کردن");
var timesArg = new Argument<int>("times", "تعداد دفعات تکرار سلام")
{
    // مقدار پیش‌فرض اختیاری
    Arity = ArgumentArity.ZeroOrOne
};
timesArg.SetDefaultValue(1); // اگر مقدار ندهیم، یک بار اجرا شود

var upperOption = new Option<bool>(
    aliases: ["--uppercase", "-u"],
    description: "خروجی را با حروف بزرگ نمایش بده");

// زیر دستور greet
var greetCommand = new Command("greet", "چاپ پیام سلام")
{
    nameArg,
    timesArg,
    upperOption
};

// این خط جادویی است! تمام پارسینگ و بایندینگ خودکار انجام می‌شود
greetCommand.SetHandler((string name, int times, bool uppercase) =>
{
    var message = uppercase 
        ? $"HELLO, {name.ToUpperInvariant()}!" 
        : $"Hello, {name}!";

    for (int i = 0; i < times; i++)
        Console.WriteLine(message);

}, nameArg, timesArg, upperOption);

// دستور ریشه (root command)
var rootCommand = new RootCommand("ابزار دمو CLI ساخته‌شده با System.CommandLine 2.0")
{
    greetCommand
};

// این دو گزینه به‌صورت خودکار اضافه می‌شوند
rootCommand.AddGlobalOption(new Option<bool>(["--version"], "نمایش نسخه"));
rootCommand.Description = "یک ابزار ساده برای تست System.CommandLine";

return await rootCommand.InvokeAsync(args);
این دقیقاً همان کاری است که در کد اولیهٔ شما بود، اما بسیار تمیزتر، خواناتر و بدون نیاز به parsed.GetRequiredValue(...).

اجرای سریع برای دیباگ (launchSettings.json)
در پوشهٔ Properties/launchSettings.json این پروفایل‌ها را اضافه کنید:
{
  "profiles": {
    "Greet Diane 3 times": {
      "commandName": "Project",
      "commandLineArgs": "greet Diane 3"
    },
    "Shout at Jack": {
      "commandName": "Project",
      "commandLineArgs": "greet Jack 1 -u"
    },
    "Shout 5 times": {
      "commandName": "Project",
      "commandLineArgs": "greet Jack 5 --uppercase"
    }
  }
}
حالا در Visual Studio یا VS Code می‌توانید مستقیماً این سناریوها را دیباگ کنید.

انتشار به‌صورت dotnet tool
dotnet pack -c Release
dotnet tool install --global --add-source ./nupkg demo
حالا در هر ترمینالی می‌توانید بنویسید:
demo greet Ali 4 -u

نکات پیشرفتهٔ نسخهٔ 2.0

اعتبارسنجی خودکار
var ageArg = new Argument<int>("age", "سن شخص");
ageArg.AddValidator(result =>
{
    if (result.GetValueOrDefault<int>() < 0)
        result.ErrorMessage = "سن نمی‌تواند منفی باشد!";
});

آپشن‌های پیچیده‌تر (مثل Enum یا List)
var colorOption = new Option<ConsoleColor>(["--color", "-c"], "رنگ متن")
{
    Arity = ArgumentArity.ExactlyOne
};

استفاده از Microsoft.Extensions.Hosting (تزریق وابستگی)
var builder = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services => services.AddSingleton<MyService>())
    .UseCommandLine(rootCommand); // این extension جدید است!

محلی‌سازی Help در نسخهٔ 2.0 می‌توانید HelpBuilder را کاملاً سفارشی کنید یا متن‌های کمک را محلی‌سازی کنید.


مشاهده مطلب اصلی