C#如何使用System.CommandLine构建功能强大的命令行工具

来源:Nodejs社区作者:深圳SEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C#如何使用System.CommandLine构建功能强大的命令行工具》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何使用System.CommandLine构建功能强大的命令行工具》有用,将其分享出去将是对创作者最好的鼓励。

System.CommandLine是微软官方提供的命令行解析库,专门用于简化C#命令行应用的开发流程,它内置了参数解析、命令管理、帮助信息生成等能力,不需要开发者手动处理复杂的字符串拆分和参数匹配逻辑。

C#如何使用System.CommandLine构建功能强大的命令行工具

基础环境准备

首先需要在项目中引入System.CommandLine的NuGet包,目前最新的稳定版本可以直接通过包管理器安装,安装完成后即可在代码中引用相关命名空间。

// 引入必要的命名空间
using System.CommandLine;
using System.CommandLine.Invocation;

定义基础命令和参数

System.CommandLine的核心逻辑是先定义命令和参数,再绑定对应的执行逻辑。最基础的命令行工具可以只有一个根命令,搭配若干参数。

定义根命令

根命令是整个命令行工具的入口,我们可以通过RootCommand类来创建根命令,同时设置命令的描述信息,这些信息会自动出现在工具生成的帮助文档中。

// 创建根命令,设置命令描述
var rootCommand = new RootCommand("这是一个示例命令行工具,用于演示System.CommandLine的基础用法");

添加参数

参数分为选项(Option)和参数(Argument)两类,选项通常以---开头,参数则是位置固定的输入值。我们可以为参数设置名称、描述、是否必填、默认值等属性。

// 定义一个字符串选项,名称为--name,描述为"输入用户名称",默认值为"默认用户"
var nameOption = new Option<string>(
    name: "--name",
    description: "输入用户名称",
    getDefaultValue: () => "默认用户"
);

// 定义一个整数参数,名称为input-number,描述为"输入一个整数",设置为必填
var numberArgument = new Argument<int>(
    name: "input-number",
    description: "输入一个整数"
);
numberArgument.Arity = ArgumentArity.ExactlyOne; // 设置参数必须传入一个值

定义好参数后,需要将参数添加到根命令中,然后绑定参数的处理逻辑。

// 将选项和参数添加到根命令
rootCommand.AddOption(nameOption);
rootCommand.AddArgument(numberArgument);

// 绑定根命令的处理逻辑
rootCommand.SetHandler((string name, int number) =>
{
    Console.WriteLine($"接收到的用户名称是:{name}");
    Console.WriteLine($"接收到的整数是:{number}");
    Console.WriteLine($"计算结果:{number} * 2 = {number * 2}");
}, nameOption, numberArgument);

执行命令

最后只需要调用根命令的InvokeAsync方法,传入命令行参数即可执行对应的逻辑,通常会把args直接传入。

// 执行命令,传入命令行参数
return await rootCommand.InvokeAsync(args);

此时如果运行程序并输入test.exe --name 张三 10,就会输出对应的处理结果,如果输入test.exe --help,会自动生成所有命令和参数的说明信息。

添加子命令

当命令行工具功能较多时,单一的根命令会导致参数混乱,此时可以使用子命令来拆分功能。比如我们可以添加一个add子命令用于计算加法,一个sub子命令用于计算减法。

// 创建add子命令
var addCommand = new Command("add", "计算两个数字的和");
// 为add子命令定义两个必填的整数参数
var addArg1 = new Argument<int>("num1", "第一个加数");
var addArg2 = new Argument<int>("num2", "第二个加数");
addCommand.AddArgument(addArg1);
addCommand.AddArgument(addArg2);
// 绑定add子命令的处理逻辑
addCommand.SetHandler((int num1, int num2) =>
{
    Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
}, addArg1, addArg2);

// 创建sub子命令
var subCommand = new Command("sub", "计算两个数字的差");
var subArg1 = new Argument<int>("num1", "被减数");
var subArg2 = new Argument<int>("num2", "减数");
subCommand.AddArgument(subArg1);
subCommand.AddArgument(subArg2);
subCommand.SetHandler((int num1, int num2) =>
{
    Console.WriteLine($"{num1} - {num2} = {num1 - num2}");
}, subArg1, subArg2);

// 将两个子命令添加到根命令
rootCommand.AddCommand(addCommand);
rootCommand.AddCommand(subCommand);

添加子命令后,运行test.exe add 5 3会输出8,运行test.exe sub 10 4会输出6,帮助信息也会自动包含子命令的说明。

参数校验和全局选项

System.CommandLine支持自定义参数校验逻辑,也支持定义全局选项,所有子命令都可以使用全局选项。比如我们可以定义一个--verbose全局选项,用于控制是否输出详细日志。

// 定义全局选项--verbose,用于控制详细日志输出
var verboseOption = new Option<bool>(
    name: "--verbose",
    description: "是否输出详细日志",
    getDefaultValue: () => false
);
// 将全局选项添加到根命令,所有子命令都可以使用
rootCommand.AddGlobalOption(verboseOption);

// 修改add子命令的处理逻辑,使用verbose选项
addCommand.SetHandler((int num1, int num2, bool verbose) =>
{
    if (verbose)
    {
        Console.WriteLine("开始执行加法计算");
        Console.WriteLine($"第一个加数:{num1},第二个加数:{num2}");
    }
    Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
    if (verbose)
    {
        Console.WriteLine("加法计算执行完成");
    }
}, addArg1, addArg2, verboseOption);

如果需要校验参数,比如要求输入的数字必须大于0,可以在参数定义时添加校验逻辑:

// 为numberArgument添加校验,要求输入的数字必须大于0
numberArgument.AddValidator(result =>
{
    var value = result.GetValueOrDefault<int>();
    if (value <= 0)
    {
        result.ErrorMessage = "输入的整数必须大于0";
    }
});

当输入不符合校验规则时,工具会自动输出错误信息,不会执行对应的处理逻辑。

完整示例代码

以下是整合了上述所有功能的完整示例代码,可以直接复制到项目中运行测试。

using System.CommandLine;
using System.CommandLine.Invocation;

class Program
{
    static async Task<int> Main(string[] args)
    {
        // 创建根命令
        var rootCommand = new RootCommand("这是一个示例命令行工具,用于演示System.CommandLine的完整用法");

        // 定义根命令的参数
        var nameOption = new Option<string>(
            name: "--name",
            description: "输入用户名称",
            getDefaultValue: () => "默认用户"
        );
        var numberArgument = new Argument<int>(
            name: "input-number",
            description: "输入一个大于0的整数"
        );
        numberArgument.Arity = ArgumentArity.ExactlyOne;
        // 添加参数校验
        numberArgument.AddValidator(result =>
        {
            var value = result.GetValueOrDefault<int>();
            if (value <= 0)
            {
                result.ErrorMessage = "输入的整数必须大于0";
            }
        });

        rootCommand.AddOption(nameOption);
        rootCommand.AddArgument(numberArgument);

        // 绑定根命令处理逻辑
        rootCommand.SetHandler((string name, int number) =>
        {
            Console.WriteLine($"接收到的用户名称是:{name}");
            Console.WriteLine($"接收到的整数是:{number}");
            Console.WriteLine($"计算结果:{number} * 2 = {number * 2}");
        }, nameOption, numberArgument);

        // 定义全局选项
        var verboseOption = new Option<bool>(
            name: "--verbose",
            description: "是否输出详细日志",
            getDefaultValue: () => false
        );
        rootCommand.AddGlobalOption(verboseOption);

        // 定义add子命令
        var addCommand = new Command("add", "计算两个数字的和");
        var addArg1 = new Argument<int>("num1", "第一个加数");
        var addArg2 = new Argument<int>("num2", "第二个加数");
        addCommand.AddArgument(addArg1);
        addCommand.AddArgument(addArg2);
        addCommand.SetHandler((int num1, int num2, bool verbose) =>
        {
            if (verbose)
            {
                Console.WriteLine("开始执行加法计算");
                Console.WriteLine($"第一个加数:{num1},第二个加数:{num2}");
            }
            Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
            if (verbose)
            {
                Console.WriteLine("加法计算执行完成");
            }
        }, addArg1, addArg2, verboseOption);

        // 定义sub子命令
        var subCommand = new Command("sub", "计算两个数字的差");
        var subArg1 = new Argument<int>("num1", "被减数");
        var subArg2 = new Argument<int>("num2", "减数");
        subCommand.AddArgument(subArg1);
        subCommand.AddArgument(subArg2);
        subCommand.SetHandler((int num1, int num2, bool verbose) =>
        {
            if (verbose)
            {
                Console.WriteLine("开始执行减法计算");
                Console.WriteLine($"被减数:{num1},减数:{num2}");
            }
            Console.WriteLine($"{num1} - {num2} = {num1 - num2}");
            if (verbose)
            {
                Console.WriteLine("减法计算执行完成");
            }
        }, subArg1, subArg2, verboseOption);

        // 添加子命令到根命令
        rootCommand.AddCommand(addCommand);
        rootCommand.AddCommand(subCommand);

        // 执行命令
        return await rootCommand.InvokeAsync(args);
    }
}

System_CommandLineC#命令行工具参数解析修改时间:2026-07-03 08:09:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。