在網站開發中,往往需要對用戶輸入的數據進行校驗。
而為了保持數據的完整性,我們需要進行客戶端和服務端的雙重校驗。
客戶端的校驗一般由js來完成,本文主要介紹利用特性完成服務器端的數據校驗。
什么是特性?
超市中有各種各樣的商品,商品上貼有標簽。標簽上可能有商品的名稱,價格,種類等信息。我們要購買一樣東西前,一般先會看標簽,了解更多的信息。當然主要是價格,萬一錢沒帶夠呢?:)
如果把類當做商品,那么特性就是貼在商品上的標簽。特性給我們提供了更多類相關的信息。[Serializable] 就是在C#中常用的一個系統的特性,通過這個特性,我們可以知道類是否允許被序列化。
特性驗證簡單Demo
我們已經了解了特性,那么如何用特性校驗數據呢?
假設用戶注冊后,通過客戶端的校驗后,將用戶名和密碼傳輸到了服務器。我們先驗證用戶名不為空,怎么做呢?
理一下思路,我們可以分3步來完成這件事情:
1、聲明一個自定義特性。
2、給用戶類添加自定義特性。
3、通過特性實現對數據的校驗。
聲明一個自定義特性。
1 [AttributeUsage(AttributeTargets.Property)] 2 class RequiredAttribute : Attribute 3 { 4 /// <summary> 5 /// 驗證失敗返回的錯誤信息 6 /// </summary> 7 public string ErrorMessage 8 { 9 get; 10 set; 11 } 12 13 /// <summary> 14 /// 輸入值 15 /// </summary> 16 public object InputValue 17 { 18 get; 19 set; 20 } 21 22 /// <summary> 23 /// 驗證規則 24 /// </summary> 25 /// <param name="errorMessage">驗證失敗返回的錯誤信息</param> 26 public RequiredAttribute(string errorMessage) 27 { 28 this.ErrorMessage = errorMessage; 29 } 30 31 /// <summary> 32 /// 接口參數為空或空字符串都返回false 33 /// </summary> 34 /// <returns></returns> 35 public bool Validate() 36 { 37 return !string.IsNullOrEmpty(InputValue.ToString()); 38 } 39 40 }
自定義特性必須繼承Attribute類,[AttributeUsage(AttributeTargets.Property)]特性表示,我們自定義的特性,只允許添加到類的屬性上。Validate()方法就是這個特性的核心邏輯,他的功能很簡單,驗證用戶輸入的值是否為空。 這個值從哪兒來呢?別急,我們一步步來。
給用戶類添加自定義特性
public class User { [Required("請輸入用戶名")] public string UserName { get; set; } public string PassWord { get; set; } }
特性可添加在類,屬性,方法,字段上。這里添加到屬性上是因為我們僅需要對屬性的值進行校驗,且我們自定義特性時聲明了特性只能添加到屬性上。 [Required("請輸入用戶名")],我們發現特性聲明就是對特性類進行實例化,圓括弧中需要傳入的參數,就是我們聲明構造函數時的參數。其實自定義特性就相當於超市中用於貼標簽的機器。
通過特性實現對數據的校驗。
我們通過讀商品的標簽就可以知道商品的信息,然后決定是不是要買。同樣用戶類中的特性也需要一個人來讀,我們肯定讀不了這個特性,那么找誰來做呢?沒錯,反射。
public string Validate() { // 反射取當前對象的所有屬性 System.Reflection.PropertyInfo[] properties = this.GetType().GetProperties(); foreach (var pInfo in properties) { // 取屬性中的特性 if (pInfo.IsDefined(typeof(RequiredAttribute),false)) { var customAttributes = pInfo.GetCustomAttributes(typeof (RequiredAttribute), false) as RequiredAttribute[]; // 根據特性進行參數驗證 foreach (var attribute in customAttributes) { // 初始化特性,並進行驗證。 var validateVal = pInfo.GetValue(this, null); attribute.InputValue = validateVal; if (!attribute.Validate()) { return "驗證失敗!消息:" + attribute.ErrorMessage; } } } } // 驗證成功 return "驗證成功!"; }
代碼的注釋已經很清楚了,就不在解釋代碼了。
還記得我們前面有個問題:用戶輸入的值的初始化問題么?其實值就是反射取屬性的值,交給我們的特性。
總結
到這兒我們再回頭看整個特性驗證的過程其實很簡單。原來我們驗證是每來一個數據都自己寫單獨的邏輯去驗證。而現在,我們將驗證的邏輯封裝到特性內,哪個數據需要就添加這個特性。數據校驗時,我們只需反射用特性來做校驗就可以了。再打個比方:我們在小攤上買東西的時候,每種商品我們都需去詢問攤主,這個買多少錢啊?而超市給每種商品都貼上了標簽,明碼標價。
項目地址
https://github.com/NemoChris/AttributeValidate/tree/v0.1/AttributeValidate
鏈接
