C# TextBox 擴充方法資料驗證詳細說明

來源:互聯網
上載者:User

查看公司項目代碼時,存在這樣一個問題:winform介面上有很多資訊填寫,提交後台伺服器更新,但資料的合法驗證及值的轉換卻不太敢恭維,一堆的if判斷和轉換,便想著是否能擴充個方法出來,琢磨出個思路,記錄下來與大家共同探討,有不對的地方還請大家指正。

設計思路:
    1. 由於大部分從TextBox控制項中擷取資料值,可以擴充個泛型方法出來,直接根據轉換後的資料類型獲得值,類似這樣,
      var value = this.txtSample.GetValue<int>();

    2. 可以傳入一個委託用來處理轉換失敗的操作,並重載此方法,提供一個預設的操作。

  好,下面開工:
    1. 建立TextBox類型的擴充方法
      引用MSDN的解釋:擴充方法使您能夠向現有類型“添加”方法,而無需建立新的衍生類別型、重新編譯或以其他方式修改原始類型。 擴充方法是一種特殊的靜態方法,但可以像擴充類型上的執行個體方法一樣進行調用。 對於用 C# 和 Visual Basic 編寫的用戶端代碼,調用擴充方法與調用在類型中實際定義的方法之間沒有明顯的差異。
      擴充方法被定義為靜態方法,但它們是通過執行個體方法文法進行調用的。 它們的第一個參數指定該方法作用於哪個類型,並且該參數以 this 修飾符為首碼。 僅當您使用 using 指令將命名空間顯式匯入到原始碼中之後,擴充方法才位於範圍中。
      注意:擴充方法是在非嵌套、非泛型靜態類內部定義的

    2. 由於轉換類型未知,但為實值型別,故採用泛型方法設計,並加上strut泛型約束,由於允許自訂處理轉換失敗時的操作,故傳入一個Action委託來實現,如下:

複製代碼 代碼如下:public static TResult GetValue<TResult>(this TextBox textBox, Action<TextBox> failed)
where TResult : struct
{
var type = typeof(TResult);
var method = type.GetMethod("TryParse", new Type[] { typeof(string), type.MakeByRefType() });
var parameters = new object[] { textBox.Text, default(TResult) };

// 若轉換失敗,執行failed
if (!(bool)method.Invoke(null, parameters))
{
failed(textBox);
throw new InvalidCastException("輸入值格式不正確,請檢查輸入值。");
}

return (TResult)parameters[1];
}

     這裡採用反射機制來調用類型的T.TryParse(string param, out T value),例如Int32.TryParse(string param,out Int32 value)等,需要注意的是:
       (1). GetMethod()方法,必須傳入合適的參數(要反射的方法的簽名)來確定方法唯一,例如碰到重載這種情況(比較常見),否則傳回值為null,方法的簽名中,若參數帶有ref 或out 關鍵字,則Type類型需要加上.MakeByRefType(),如上。
       (2). 得到唯一的方法執行個體後,可以傳入相應的參數,調用Invoke方法來實現方法的調用,MethodInfo.Invoke(object obj, object[] parameters)方法第一個參數為反射調用該方法的對象,如果為靜態方法(比如本例),可以傳入null,第二個參數為方法的參數,順序必須與方法簽名一致。
       (3). 方法參數中帶有ref和out關鍵字,獲得該值通過參數數組來獲得。如本例中:parameters[1]

    3. 定義轉換失敗操作的委託
      C#內建封裝的委託有兩種,Action和Func委託,並有很多的重載版本,參數可以有十多個,所以不用擔心參數問題。其中Action委託無傳回值,屬於Void類型,Func委託具有傳回值,如Func<T,TResult>,在Linq操作中比較常見,在該例中,無傳回值的必要,故採用Action委託,由於需要處理轉換失敗的操作,故將TextBox作為該委託的參數裡進行處理,如代碼所示,當轉換失敗時進行處理:   
        // 若轉換失敗,執行failed
         if (!(bool)method.Invoke(null, parameters))
           failed(textBox);
      在此簡單介紹下委託:委託其實是一個類型,通過反編譯工具可以看出來,當構造委託時傳入一個方法,其實會隱形的傳入兩個參數(target,methodPtr),target參數為調用該方法的執行個體,若靜態方法,則為null,methodPtr為傳入方法的記憶體位址(在中繼資料中存貯該資訊),faild(textBox)表面看不太好理解,為什麼一個對象後面帶一個參數,其實C#編譯器為我們做了很多工作,在這裡實質為faild.Invoke(textBox),這樣看還好理解委託是個類型,通過faild的委派物件來調用該委託所註冊的方法。

    4. 建立重載版本:
      用lambda運算式定義預設的轉換失敗操作,如果轉換失敗,則提示資訊,並全部選中和定位到該輸入框上。

複製代碼 代碼如下:public static TResult GetValue<TResult>(this TextBox textBox, bool isShowError)
where TResult : struct
{
return GetValue<TResult>(textBox, p =>
{
if (isShowError)
{
p.Focus();
p.SelectAll();
MessageBox.Show("輸入值格式不正確,請重新輸入!",
"提示--實值型別:" + typeof(TResult).Name,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
});
}

複製代碼 代碼如下:///預設版本,調用上個重載方法

public static TResult GetValue<TResult>(this TextBox textBox)
where TResult : struct
{
return GetValue<TResult>(textBox, true);
}

5. 實驗測試:
      建立winform程式,介面:

後台代碼:

複製代碼 代碼如下:private void btnConvert_Click(object sender, EventArgs e)
{
try
{
var intValue = txtInt.GetValue<int>();
var floatValue = txtFloat.GetValue<float>();
var dateTimeValue = txtDateTime.GetValue<DateTime>();
var doubleValue = txtDouble.GetValue<double>();
}
catch (Exception) { }
}

如果輸入值非法,則提示錯誤,:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.