Dotnet Core 優雅的命令行實現
本文轉載自微信公眾號「老王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()
不需要管 python3 是什么,這不重要。
我們能看到,當進入一個命令行時,一般首先會有簡單的功能介紹,然后是一個提示符,在這里是 >>>。然后可以輸入命令和參數,如果輸入正確,會有錯誤提示。如果輸入正確,會有適當的輸出。
通常,如果想實現這樣的效果,我們需要一個大的循環,來解析和響應輸入的命令和參數,然后進行對應的處理。
事實上,在做這樣一個應用時,會有很大的精力來處理這個循環。不相信的話,可以自己試著寫一寫。
今天給大家介紹的,是一個庫,Nuget 上的庫,也是我最近無意中發現的,但給了我很大的驚喜。事實上,我自己在寫應用時,如果有可能,我會優先采用 Console 或 Cli 的方式來寫,輕量、快速,不用處理太多 UI 方面的工作。
這個庫叫 CommandLineTool。
下面進入正題,我從頭介紹一下這個庫的使用。
創建項目
先來創建項目。老習慣,用命令行創建:
- % dotnet new console -o demo -f net5.0
這兒需要注意一下,這個庫目前支持到 Dotnet Core 5.0,所以我們就用 5.0 了。
然后,引入 CommandLineTool:
- % dotnet add package CommandLineTool
就這樣,工程就算是建完了。
實現功能
這個庫最簡單的地方,是實現起來非常簡單。
第一步,先建一個類
這個類,就是我們要實現 Cli 命令行功能的類 TestCLI:
- [App("Demo")]
- public class TestCLI
- {
- }
類是空的,先不管它。
第二步,在 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();
- }
- }
看一個加入的內容:
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...
哇哈哈,一個簡單的 Cli 架子搭出來了。
第三步,開始寫命令處理
命令處理放在 TestCLI.cs 中。
- [App("Demo")]
- public class TestCLI
- {
- [Command("hello", "就是打個招呼")]
- public static void Hello([ParamArgument()] string name)
- {
- Console.WriteLine($"Hello {name}");
- }
- }
方法還是我們非常熟悉的一個普通方法,并沒有什么特別的。
再跑一下:
- 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
出來效果了。
重點看一下代碼里的幾個部分:
屬性 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) {}
重點說一下額外參數的方式。
有時候,我們可能需要下面的方式來處理命令:
- % demo -a a-value -b b-value command
這個方式,就是來解決這樣的問題的。
有沒有 Get 到爽點?
本文有配套代碼,在 https://github.com/humornif/Demo-Code/tree/master/0053/demo