用特性來實現數據的校驗


在網站開發中,往往需要對用戶輸入的數據進行校驗。
而為了保持數據的完整性,我們需要進行客戶端和服務端的雙重校驗。
客戶端的校驗一般由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


鏈接

特性驗證完結版

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM