本文转载自微信公众号「老王Plus」,作者老王Plus的老王。转载本文请联系老王Plus公众号。
控制台应用 Console,在我们开发中用处很多。小到一个简单的功能测试,或一组不需要复杂 UI 的工具类应用,大到后端的服务,都会用到 Console。
在这里面,命令行应用 Cli,又是非常典型的一个应用类型。
命令行应用,通常概念上需要我们输入一定参数,根据参数的不同,选择不同的程序流程或方法来执行。
举个简单的例子:
复制
% python3 Python 3.9.0 (default, Nov 13 2020, 12:12:14) [Clang 12.0.0 (clang-1200.0.32.21)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import OS Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'OS' >>> import os >>> print("Hello WangPlus") Hello WangPlus >>> exit()
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
不需要管 python3 是什么,这不重要。
我们能看到,当进入一个命令行时,一般首先会有简单的功能介绍,然后是一个提示符,在这里是 >>>。然后可以输入命令和参数,如果输入正确,会有错误提示。如果输入正确,会有适当的输出。
通常,如果想实现这样的效果,我们需要一个大的循环,来解析和响应输入的命令和参数,然后进行对应的处理。
事实上,在做这样一个应用时,会有很大的精力来处理这个循环。不相信的话,可以自己试着写一写。
今天给大家介绍的,是一个库,Nuget 上的库,也是我最近无意中发现的,但给了我很大的惊喜。事实上,我自己在写应用时,如果有可能,我会优先采用 Console 或 Cli 的方式来写,轻量、快速,不用处理太多 UI 方面的工作。
这个库叫 CommandLineTool。
下面进入正题,我从头介绍一下这个库的使用。
先来创建项目。老习惯,用命令行创建:
复制
% dotnet new console -o demo -f net5.0
1.
这儿需要注意一下,这个库目前支持到 Dotnet Core 5.0,所以我们就用 5.0 了。
然后,引入 CommandLineTool:
复制
% dotnet add package CommandLineTool
1.
就这样,工程就算是建完了。
这个库最简单的地方,是实现起来非常简单。
第一步,先建一个类
这个类,就是我们要实现 Cli 命令行功能的类 TestCLI:
复制
[App("Demo")] public class TestCLI { }
1.
2.
3.
4.
类是空的,先不管它。
第二步,在 Program.cs 里加入这个类
复制
class Program { static void Main(string[] args) { Cli cli = new Cli(typeof(TestCLI)) { Introduction = "这是一个 Demo 应用", PromptText = "WangPlus", }; cli.SetCancellationKeys(new() { "exit" }); cli.Start(); } }
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
看一个加入的内容:
Introduction - 这个 Cli 的说明,提示一下这个程序的功能,随便写;
PromptText - 这个是提示符的内容,类似于最上面例子的 >>>;
下面这一句cli.SetCancellationKeys(new() { "exit" });,是定义了退出的命令。也就是说,在提示符后输入 exit,应用就退出了。
跑一下这个应用:
复制
% dotnet demo.dll 这是一个 Demo 应用 WangPlus > ? '?' was not matched. Did you mean '-h'? Unrecognized command or argument '?' demo Demo Usage: demo [options] Options: --version Show version information -?, -h, --help Show help and usage information WangPlus >exit Terminating console...
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
哇哈哈,一个简单的 Cli 架子搭出来了。
第三步,开始写命令处理
命令处理放在 TestCLI.cs 中。
复制
[App("Demo")] public class TestCLI { [Command("hello", "就是打个招呼")] public static void Hello([ParamArgument()] string name) { Console.WriteLine($"Hello {name}"); } }
1.
2.
3.
4.
5.
6.
7.
8.
9.
方法还是我们非常熟悉的一个普通方法,并没有什么特别的。
再跑一下:
复制
WangPlus >hello Required argument missing for command: hello hello 就是打个招呼 Usage: demo [options] hello <name> Arguments: <name> Options: -?, -h, --help Show help and usage information WangPlus >hello wang Hello wang
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
出来效果了。
重点看一下代码里的几个部分:
属性 Command,里面两个参数,第一个参数就是我们要实现的命令,第二个参数是命令的说明。
方法里,[ParamArgument()] 表示后面跟的参数来自于输入的命令的参数。
下面还有几种形式:
复制
//多个参数 [Command("multiinput", "多个参数")] public static void MultiInput([ParamArgument()] List<string> names) {} //多个文件 [Command("multifile", "多个文件")] public static void MultiFile([ParamArgument()] List<FileInfo> files) {} //额外的参数 [Command("withpara", "额外参数")] public static void WithPara([ParamArgument()] string names, [ParamOption("-a")] string op1) {}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
重点说一下额外参数的方式。
有时候,我们可能需要下面的方式来处理命令:
复制
% demo -a a-value -b b-value command
1.
这个方式,就是来解决这样的问题的。
有没有 Get 到爽点?
本文有配套代码,在 https://github.com/humornif/Demo-Code/tree/master/0053/demo