﻿# 介紹好用元件：ConsoleFx ( 處理命令列程式的函示庫 )

我之前寫 Console Program 時都是自己分析執行時輸入的參數，程式碼寫的也很醜，也很難 reuse，導致每次開發 Console Program 的程式碼都不太一致，有時後為了方便起見就亂寫一通，等累積多了之後就變的不好維護了。

最近在 [CodePlex](http://www.codeplex.com/) 發現了一個 [ConsoleFx](http://www.codeplex.com/ConsoleFx) 專案，提供一套很方便的開發架構，他把一些在 Console 模式下開發 .NET 程式會處理的程式碼都寫好了，尤其是對參數、例外狀況、輸入資料格式驗證等常見的程式尤其方便，不但省去了許多開發時間，也提供了一致的開發架構，程式碼也會比較容易維護。

一般來說，若有用過指令列工具時，通常只要在指令後面加上 /? 就會出現使用說明，例如：

```
CLEAN [-dir:<directory mask>] [-file:<file mask>] [-norecurse] <base directory>
```

當使用 [ConsoleFx](http://www.codeplex.com/ConsoleFx) 時會用到一些**專有名詞**需先解說一下，這也是一般在寫 Console Program 時都應該到的東西：

1.  Switch
    -   如以上範例的 **\-dir** 或 **\-norecurse** 就是所謂的 Switch。
    -   通常以減號(–)或以斜線(/)開頭。
    -   通常使用 Switch 的目的在於設定 Console Program 執行時的選項。
2.  Switch Parameters
    -   如以上範例的 <directory mask> 或 <file mask> 就是該 Switch 的參數。
3.  Parameters
    -   如以上範例的 <base directory> 就是該程式的主要參數。
    -   主要參數前面沒有接著 Switch，而是獨立存在的參數。

**ConsoleFx 1.0 提供的功能與特色有**

-   輸入的參數可透過 Attribute 宣告與 Property 搭配使用
    -   將輸入的參數轉成屬性(Property)好處是可以在程式中可直接存取輸入參數，無須在讀取 params\[\] 字串陣列。
-   可限制 switch 與 parameter 參數輸入的順序、格式、與參數出現的次數
    -   所有的設定都是透過 Attributes 宣告完成。
-   輸入參數驗證(Switch validation)
    -   可透過設定屬性(Attribute)的方式設定 switch 的參數是否符合定義。
    -   目前可驗證的資料類型有:
        -   Boolean
            -   驗證輸入參數是否為 Boolean 格式 ( True/False )
        -   Integer
            -   可驗證輸入是否為數字
        -   Lookup
            -   可提供一組字串清單，用逗號( , )分隔，用以驗證輸入的參數是否符合格式
                
                ```
                [LookupValidator(ParameterIndex.FirstParameter, "SHA1,MD5")]
                ```
                
        -   Enum
            -   功能雷同於 Lookup 驗證類別，差別在於改以 Enum 型別定義可輸入的字串
            -   可指定一個 Enum 型別，讓輸入的參數必須符合 Enum 中定義的名稱
        -   Path
            -   檢查輸入的參數是否回有效路徑
            -   也可檢查檔案、目錄是否存在
        -   Regex
            -   可自訂 Regex 樣式比對輸入的字串
        -   String
            -   可限定輸入字串的長度
    -   驗證的類型你還可以透過繼承 BaseValidatorAttribute 來擴充。
-   錯誤處理(Error handling)
    -   當程式執行發生例外狀況(Exceptions)，預設的錯誤訊息都集中在 ConsoleFx.CommandLineException.Message 類別中，你可以直接修改這個類別中的常數自訂顯示的錯誤訊息。
    -   另外你也可以在 Validator 類別中自訂當驗證失敗後的錯誤訊息。
-   簡化常見的使用情境(Simplify common usage scenarios)
    -   只要繼承 ConsoleFx.ConsoleProgram 基底類別，就僅需覆寫(override)以下 2 個方法程式就會自動接受 /h 或 -h 參數(switch)，若有加上 -h 就會自動執行 DisplayUsage() 方法，否則就會自動進入 ExecuteNormal() 方法執行：
        -   public override void DisplayUsage()
        -   public override int ExecuteNormal(string\[\] parameters)

目前來說 [ConsoleFx Command Line Processing Library](http://www.codeplex.com/ConsoleFx) 線上所提供的文件並不多，但有點經驗的 .NET 開發人員應該很容易就可以從 Sample Code 中看懂他的使用方法。

**最後分享一些使用心得**

-   初始 ConsoleFX 專案的基本流程如下：
    1.  新增 Console Application 專案
    2.  加入 ConsoleFX 參考
    3.  修改 Program.cs 的內容，範本如下：
        
        ```
        using ConsoleFx;
        using ConsoleFx.Validators;
        
        namespace ConsoleApplication1
        {
            [CommandLine(Grouping=CommandLineGrouping.DoesNotMatter)]
            class Program : ConsoleProgram
            {
                public static int Main(string[] args)
                {
                    return CommandLine.Run<Program>(args);
                }
        
                public override void DisplayUsage()
                {
                    ConsoleEx.WriteLine("ConsoleApplication1.exe [/SwitchA:<switch_parameter>] [<param1>] [...]");
                }
        
                string _switch_a;
        
                [Switch("SwitchA", ShortName = "a", MaxOccurences = 1, CaseSensitive = false, Order = 1)]
                [SwitchUsage(ProgramMode.Help, SwitchUsage.NotAllowed)]
                [SwitchUsage(ProgramMode.Normal, SwitchUsage.Optional)]
                [StringValidator(ParameterIndex.FirstParameter, MinLength = 1, MaxLength = 10)]
                public void SwitchA(string[] parameters)
                {
                    if (parameters.Length > 0)
                    {
                        _switch_a = parameters[0];
                    }
                }
        
                public override int ExecuteNormal(string[] parameters)
                {
                    return 0;
                }
            }
        }
        ```
        
        注意：ConsoleFX 中的 Main 回傳值是 int 喔。
-   所有的 switch 選項參數要套用必須用**公開方法**(public method)實做。
    
    ```
    [Switch("algorithm", ShortName = "a", MinParameters = 0, MaxParameters = 1)]
    [SwitchUsage(ProgramMode.Help, SwitchUsage.NotAllowed)]
    [SwitchUsage(ProgramMode.Normal, SwitchUsage.Optional)]
    [LookupValidator(ParameterIndex.FirstParameter, "SHA1,MD5,SHA256,SHA384,SHA512")]
    public void AlgorithmSwitch(string[] parameters)
    {
        if (parameters.Length > 0)
            _algorithm = parameters[0];
    }
    ```
    
-   Parameters 一般參數可套用在**公開屬性**(public property)上，以強型別的方式運作。
    
    ```
    [ParameterProperty(ProgramMode.Normal, 1)]
    [PathValidator(ProgramMode.Normal, PathType=PathType.Folder, CheckIfExists=true)]
    [StringValidator(ParameterIndex.FirstParameter, MinLength = 1, MaxLength = 100)]
    public string Path
    {
        get {
            return _path;
        }
        set {
            _path = value;
        }
    }
    ```
    
-   ExecuteNormal() 若正常執行回傳值應為 0，若有錯誤發生應回應非 0 的值。
-   ExecuteNormal(string\[\] parameters) 傳入的 Parameters 不會有 switch 的任何參數。
-   如果你有部分參數 Binding 到 Property 中，這些參數還是會以 string 的型態傳到 ExecuteNormal() 中。
-   ConsoleFX 專案有兩種執行模式(ProgramMode)：
    -   ProgramMode.Normal
        -   正常執行 Console Application 的情況。
    -   ProgramMode.Help
        -   進入/顯示 Help 選單時的模式。
-   ConsoleFX 專案的執行模式(ProgramMode)可自訂擴充，例如你若要從 Console Application 啟動 Windows Form 的程式時，可以自訂一個 Mode 叫做 ProgramMode.Windows 。

**相關連結**

-   [ConsoleFx Command Line Processing Library](http://www.codeplex.com/ConsoleFx)
-   [ConsoleFx Documentation](https://github.com/JeevanJames/ConsoleFx)
