用 System.CommandLine 定义强类型命令行参数
System.CommandLine 的核心优势是把命令行输入直接映射为 C# 对象,避免手动拆解
args字符串。关键不是“怎么加参数”,而是“怎么让参数自动变成你想要的类型和结构”。
比如定义一个发布命令:
myapp publish --project MyApp.csproj --configuration Release --output ./bin,你可以这样建模: 用
Option<string></string>表示单值参数(如
--project),指定别名(
-p)、描述、是否必需 用
Option<ilist>></ilist>支持多次出现的参数(如
--property Key=Value可重复) 用
Argument<string></string>处理位置参数(如
myapp run api中的
api) 所有选项/参数都可绑定到
Handler方法的参数上,System.CommandLine 自动完成转换和验证
用 Handler 和泛型委托实现零反射调用
老式做法常依赖反射调用方法,而 System.CommandLine 推荐用强类型委托,既安全又高效。不用写
typeof(...).GetMethod(...).Invoke()这类易错代码。
例如:
var publishCommand = new Command("publish", "Publish a .NET project");
publishCommand.AddOption(projectOption);
publishCommand.AddOption(configOption);
publishCommand.AddOption(outputOption);
<p>publishCommand.Handler = CommandHandler.Create<string, string, string>(PublishHandler);</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/ai/1915" title="Summarizer"><img
src="https://www.herecours.com/d/file/efpub/2026/21-21/20260221135947179329.jpg" alt="Summarizer" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/ai/1915" title="Summarizer">Summarizer</a>
<p>基于 AI 的文本段落摘要生成器</p>
</div>
<a href="/ai/1915" title="Summarizer" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div><p>// 方法签名完全匹配,自动注入解析后的值
static void PublishHandler(string project, string configuration, string output)
{
Console.WriteLine($"Publishing {project} in {configuration} to {output}");
}</p>注意:参数名必须和
Option.Argument.GetDefaultValue()或绑定名一致;如果想用不同名,可用
Option<t>.Alias</t>或
Option<t>.SetName()</t>显式对齐。
支持子命令 + 共享选项 + 配置复用
真实 CLI 工具往往有层级,比如
git commit、
git push。System.CommandLine 原生支持子命令嵌套,还能让多个子命令共用一组基础选项(如
--verbose、
--dry-run)。 用
RootCommand.AddCommand(subCmd)构建树形结构 共享选项不绑定到具体命令,而是添加到
RootCommand,再通过
InvocationContext.ParseResult.GetValueForOption()在各 handler 中按需读取 也可用
Command.AddGlobalOption()(.NET 7+)自动下推到所有子命令 配合
ParseResult.FindResultFor()可判断某个选项是否被显式传入(区别于默认值)
自定义解析逻辑与错误处理更可控
当标准类型转换不够用(比如要解析自定义时间格式、枚举别名、文件路径存在性校验),System.CommandLine 允许你插入自己的转换器和验证器。
用option.ParseArgument = result => { /* 自定义逻辑 */ } 替换默认解析
用 option.AddValidator(opt => { if (...) return "Invalid format"; }) 提供友好错误提示
全局异常处理可通过 CommandLineBuilder.UseExceptionHandler()捕获
CommandException等,并输出结构化帮助或退出码 错误消息不会直接抛出堆栈,而是走内置渲染器,保持 CLI 体验统一
基本上就这些。System.CommandLine 的高级用法,核心是“声明即契约”——你定义的 Option、Argument、Handler 就是用户能输入什么、程序会收到什么、出错时反馈什么。不复杂但容易忽略的是:别急着写逻辑,先花十分钟把命令结构用对象模型画清楚。
