在寫 Console 程式時,最麻煩的就是設定參數,最一般的方式就是判斷 main 傳進來的 args 裡面有什麼值,但這樣的方式會讓程式不好維護,而筆者最近發現的 CommandLineUtils 剛好可以解決這樣的問題。

安裝

利用 nuget 搜尋 “McMaster.Extensions.CommandLineUtils” 後,直接安裝即可。

範例

首先定義一個類別,決定它的參數有哪些:

[HelpOption("--help")]
public class CommandLineParametersClass
{
    public CommandLineParametersClass()
    {
        _client = new HttpClient();
    }

    private HttpClient _client;

    [Option(Description = "show app version")]
    public bool Version { get; set; }

    [Option(Description = "set url", ShortName = "u")]
    [Required]
    public string Baseurl { get; set; }

    [Option(Description = "url route")]
    public string Path { get; set; }

    [Option(Description = "HTTP Method")]
    public (bool hasValue, string method) Method { get; set; } = (true, "GET");

    [Option(Description = "post body")]
    public string Body { get; set; }
}

最上層的 [HelpOption("--help")] 就是設定程式的 help 指令,而在每個 property 上設定的 option,就是將它設為程式的參數,像是 Version property,它的指令就會自動被設為 -v--version。其中 [Required] 就是程式的必要參數,沒加的話程式會直接拋出例外。

而 Option 中裡面的 Description 是給 help 指令顯示用的,用來說明參數的功用,如下圖:

最後,類別還要再加上執行的邏輯:

private void PrintResult(string result)
{
    Console.WriteLine(result);
}

private void OnExecute()
{
    string result = string.Empty;

    if (Version)
    {
        Console.WriteLine("version is: 0.1");
        return;
    }

    _client.BaseAddress = new Uri(Baseurl);
    HttpResponseMessage response = null;
    if (string.IsNullOrEmpty(Path))
    {
        Path = "/";
    }
    if (Method.hasValue && Method.method == "POST")
    {
        HttpContent contentPost = new StringContent(Body, Encoding.UTF8, "application/json");
        response = _client.PostAsync(Path, contentPost).Result;
        result = response.Content.ReadAsStringAsync().Result;
        PrintResult(result);

        return;
    }
    response = _client.GetAsync(Path).Result;
    result = response.Content.ReadAsStringAsync().Result;
    PrintResult(result);
}

class Program
{
    public static int Main(string[] args) => CommandLineApplication.Execute<CommandLineParametersClass>(args);
}

由於 CommandLineUtils 會自動將值塞入 property 中,所以直接檢查 property 就行了,而在 main function 中也直接簡化為 public static int Main(string[] args) => CommandLineApplication.Execute<CommandLineParametersClass>(args); 即可。

參考資料