惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 世纪末の魔术师

坚毅,是一种缓慢修理自己的方式 语言的边界,与软件的命运 人类与AI协同进化 《坚毅》第一部分读书笔记 用 Command 模式构建可扩展的命令行工具 从哎呦”到语言宇宙 ——读《What Is ChatGPT Doing … And Why Does It Work?》 ⏱️ 深入理解定时器中的【时间轮算法】 🚫 为什么「定时器」不应该是线程安全的? C# AOT编译后——调用其类库方法因顺序出错? UnitTask中的Forget()与 CTS 光线追踪和球体追踪 八、方法(method) 二十、异常与状态管理(Exception&State Management) 二十八、IO绑定的异步操作(IO-Bound Async) 二十二、CLR寄宿与AppDomain(CLR Hosting and App Domains ) 二十九、原始线程同步构造(Primitive Thread Synchronization Constructs ) 二十六、线程与并发(Thread Basic) 二十七、计算密集型异步操作(Compute-Bound Asynchronous Operations) 二十三、程序集加载与反射(Assembly Loading and Reflection)
用 System.CommandLine 构建工程级 CLI 工具
世纪末の魔术师 · 2026-01-22 · via 博客园 - 世纪末の魔术师

用 System.CommandLine 构建工程级 CLI 工具

—— 从“手写 Command 模式”到工业级命令行框架

在实际工程中,我们经常需要构建工具型程序

  • 数据预处理工具
  • 离线算法管线
  • 图像 / 点云 / 配置文件批处理
  • Unity / C# 项目的辅助命令行工具

一开始,最自然的做法是:
👉 使用 Command Pattern(命令模式)自行实现一套 CLI 调度系统

这在架构上是完全正确的

但当命令逐渐增多、参数变复杂之后,你会发现:

我们并不是在实现“业务命令”,
而是在不断重复造一个 命令行解析框架

这正是 System.CommandLine 存在的意义。

一、回顾:传统的 Command 模式 CLI 设计

典型的手写方案通常长这样:

- ICommand
- CommandGenerate
- CommandParse
- CommandExport
- Program.cs 中手动解析 args
- switch / dictionary 做 dispatch

这种方式的优点

  • 命令解耦
  • 易扩展
  • 符合 Command Pattern
  • 业务逻辑清晰

但问题也很明显

  • 参数解析需要自己写
  • --help / usage 要自己维护
  • 子命令嵌套成本高
  • 参数校验、默认值、类型转换重复劳动

问题不在设计,而在“你做了太多框架层的工作”。

二、System.CommandLine 是什么?

一句话定义:

System.CommandLine 是微软官方提供的、
基于 Command Pattern 的命令行应用框架

它做的事情只有一件:

把“命令行解析 + 路由”这层脏活累活标准化

而你只需要关心:

  • 命令是什么
  • 参数是什么
  • 业务逻辑是什么

三、核心设计思想(重要)

很多人误解 System.CommandLine 是“替代 Command 模式”。

实际上正好相反:

System.CommandLine 是 Command 模式在 CLI 场景下的成熟实现

你之前的设计思想是对的,只是:

  • ❌ 手写了解析和调度
  • ✅ 现在交给框架

四、整体结构设计(推荐)

一个工程级 CLI 工具,我推荐这样的结构:

ProjectRoot
│
├── Program.cs              // CLI 装配层
│
├── Commands/               // 命令定义层
│   ├── GenerateCommand.cs
│   ├── ParseCommand.cs
│   └── ExportCommand.cs
│
├── Services/               // 核心业务
│   ├── Generator.cs
│   ├── Parser.cs
│   └── Exporter.cs
│
└── Infrastructure/
    └── PathResolver.cs

👉 Command 层不写业务,只表达“意图”

五、最小可用示例

1️⃣ Program.cs:只负责注册命令

using System.CommandLine;

var root = new RootCommand("Sample CLI Tool");

root.AddCommand(GenerateCommand.Build());
root.AddCommand(ParseCommand.Build());

return await root.InvokeAsync(args);

没有 switch,没有 if,没有手写解析。

2️⃣ 一个命令 = 一个文件

using System.CommandLine;

public static class GenerateCommand
{
    public static Command Build()
    {
        var command = new Command(
            "generate",
            "Generate output from input data"
        );

        var input = new Option<string>(
            "--input",
            description: "Input file path"
        ) { IsRequired = true };

        var output = new Option<string>(
            "--output",
            description: "Output file path"
        ) { IsRequired = true };

        command.AddOption(input);
        command.AddOption(output);

        command.SetHandler((string i, string o) =>
        {
            Console.WriteLine($"Generate: {i} -> {o}");
            // Generator.Run(i, o);
        }, input, output);

        return command;
    }
}

3️⃣ 自动获得的能力

不需要你写任何额外代码,就已经支持:

tool generate --input data.json --output result.bin
tool generate --help
tool --help

包括:

  • 参数校验
  • Help 文档
  • 子命令结构
  • 类型安全绑定

六、支持 --relative / --absolute 的工程实践

在实际项目中,路径处理是高频需求。

推荐做法是:

  • CLI 层只接收“路径意图”
  • 路径解析统一放到 Infrastructure 层
public static class PathResolver
{
    public static string Resolve(string path, bool relative)
    {
        return relative
            ? Path.GetFullPath(path)
            : path;
    }
}

Command 里只做:

var relative = new Option<bool>("--relative", "Use relative path");

👉 这样命令层保持干净,后续也方便迁移到 GUI / Editor 工具。

七、和手写 Command 模式的关系

架构思想 Command Pattern Command Pattern 参数解析 自己写 框架内置 Help 文档 自维护 自动生成 扩展成本 中 低 工业成熟度 自制 官方
维度 手写 Command System.CommandLine

这不是推翻重来,而是自然升级。

八、适用场景总结

System.CommandLine 非常适合:

  • 离线工具
  • 算法管线
  • Unity / C# 辅助工具
  • 内部工程工具
  • 自动化脚本入口

如果你发现自己正在:

“为了 CLI 写大量非业务代码”

那就是一个明确的信号
👉 该用它了。

结语

命令模式本身没有问题,
问题在于:你不该在每个项目里重复造轮子

System.CommandLine 做的不是“帮你偷懒”,
而是把精力从框架层解放出来,让你专注真正重要的事。\