1. 程式人生 > >參數聲明式校驗

參數聲明式校驗

ima 代碼 ace () img stat 構造函數 名稱 format)

用戶輸入都是不可信的,我想,大多數後端開發人員,都有這麽一個共識。

然後,在寫每一個方法的時候,基本都會有一坨if校驗,我也不例外。

代碼寫多了,有時候就會想,能不能優化下,能不能優雅點?

於是,我又開始尋尋覓覓...
這個,就是,聲明式驗證...

以下是我整理的代碼:

聲明式驗證核心部分:

技術分享
1     public enum ValidateType
2     {
3         IsString = 10000,
4         IsInt32 = 20000,
5         IsDecimal = 30000,
6         IsDateTime = 40000,
7         IsBoolean = 50000
, 8 }
View Code 技術分享
  1     [AttributeUsage(AttributeTargets.All)]
  2     public class ValidateAttribute : Attribute
  3     {
  4         //是否必填
  5         private bool isRequired = true;
  6         //最小長度
  7         private int minLength = 0;
  8         //最大長度
  9         private int maxLength = Int32.MaxValue;
10 //字段指定長度 11 private int stringLength = Int32.MaxValue; 12 //驗證類型 13 private ValidateType validateType; 14 15 /// <summary> 16 /// 顯示名稱 17 /// </summary> 18 public string DisplayName { get; set; } 19 20 /// <summary>
21 /// 是否必填 22 /// </summary> 23 public bool IsRequired 24 { 25 get 26 { 27 return isRequired; 28 } 29 set 30 { 31 isRequired = value; 32 } 33 } 34 35 /// <summary> 36 /// 最小長度 37 /// </summary> 38 public int MinLength 39 { 40 get 41 { 42 return minLength; 43 } 44 set 45 { 46 minLength = value; 47 } 48 } 49 50 /// <summary> 51 /// 最大長度 52 /// </summary> 53 public int MaxLength 54 { 55 get 56 { 57 return maxLength; 58 } 59 set 60 { 61 maxLength = value; 62 } 63 } 64 65 /// <summary> 66 /// 字段指定長度 67 /// </summary> 68 public int StringLength 69 { 70 get 71 { 72 return stringLength; 73 } 74 set 75 { 76 stringLength = value; 77 } 78 } 79 80 /// <summary> 81 /// 正則表達式校驗格式 82 /// </summary> 83 public string RegexpCheckFormat { get; set; } 84 85 /// <summary> 86 /// 正則表達式顯示格式 87 /// </summary> 88 public string RegexpDisplayFormat { get; set; } 89 90 /// <summary> 91 /// Int32集合 92 /// </summary> 93 public int[] Int32Collection { get; set; } 94 95 /// <summary> 96 /// 字符串集合 97 /// </summary> 98 public string[] StringCollection { get; set; } 99 100 /// <summary> 101 /// 驗證類型 102 /// </summary> 103 public ValidateType ValidateType 104 { 105 get 106 { 107 return validateType; 108 } 109 set 110 { 111 validateType = value; 112 } 113 } 114 115 /// <summary> 116 /// 構造函數 117 /// </summary> 118 /// <param name="validateType"></param> 119 public ValidateAttribute(ValidateType validateType) 120 { 121 this.validateType = validateType; 122 } 123 }
View Code 技術分享
  1     public static class ValidateHandler
  2     {
  3         /// <summary>
  4         /// 獲得結果
  5         /// </summary>
  6         /// <param name="instance">類對象實例</param>
  7         /// <returns></returns>
  8         public static string GetResultString(object instance)
  9         {
 10             var result = string.Empty;
 11             if (instance.IsNull())
 12             {
 13                 return "instance 參數不能為空";
 14             }
 15             Type type = instance.GetType();
 16             PropertyInfo[] properties = type.GetProperties();
 17             foreach (PropertyInfo property in properties)
 18             {
 19                 //獲取驗證特性
 20                 object[] validAttrs = property.GetCustomAttributes(typeof(ValidateAttribute), true);
 21                 if (!validAttrs.IsNull())
 22                 {
 23                     //獲取屬性的值
 24                     object propVal = property.GetValue(instance, null);
 25                     //屬性值長度
 26                     int propValLength = 0;
 27                     foreach (ValidateAttribute validAttr in validAttrs)
 28                     {
 29                         //獲取屬性名稱
 30                         var propName = !validAttr.DisplayName.IsNullOrEmptyOrWhiteSpace() ? validAttr.DisplayName : property.Name;
 31                         //校驗是否必填
 32                         if (validAttr.IsRequired)
 33                         {
 34                             if (propVal.IsNull())
 35                             {
 36                                 return "{0} 字段是必需的".FormatWith(propName);
 37                             }
 38                             if (validAttr.ValidateType == ValidateType.IsString
 39                                 && propVal.ToString().IsNullOrEmptyOrWhiteSpace())
 40                             {
 41                                 return "{0} 字段是必需的".FormatWith(propName);
 42                             }
 43                             if (validAttr.ValidateType == ValidateType.IsInt32
 44                                 && !propVal.IsInt32())
 45                             {
 46                                 return "{0} 字段不是Int32類型".FormatWith(propName);
 47                             }
 48                             if (validAttr.ValidateType == ValidateType.IsDecimal
 49                                 && !propVal.IsDecimal())
 50                             {
 51                                 return "{0} 字段不是Decimal類型".FormatWith(propName);
 52                             }
 53                             if (validAttr.ValidateType == ValidateType.IsDateTime)
 54                             {
 55                                 if (!propVal.IsDateTime())
 56                                 {
 57                                     return "{0} 字段不是日期類型".FormatWith(propName);
 58                                 }
 59                                 if (propVal.ToDateTime() == DateTime.MinValue)
 60                                 {
 61                                     return "{0} 字段是必需的".FormatWith(propName);
 62                                 }
 63                             }
 64                             if (validAttr.ValidateType == ValidateType.IsBoolean
 65                                 && !propVal.IsBoolean())
 66                             {
 67                                 return "{0} 字段不是布爾類型".FormatWith(propName);
 68                             }
 69                         }
 70                         propValLength = propVal.IsNull() ? 0 : propVal.ToString().Length;
 71                         //校驗最小長度
 72                         if (propValLength < validAttr.MinLength)
 73                         {
 74                             return "{0} 字段或數組長度不能小於{1}".FormatWith(propName, validAttr.MinLength);
 75                         }
 76                         //校驗最大長度
 77                         if (propValLength > validAttr.MaxLength)
 78                         {
 79                             return "{0} 字段或數組長度不能大於{1}".FormatWith(propName, validAttr.MaxLength);
 80                         }
 81                         if (validAttr.StringLength != Int32.MaxValue
 82                             && propValLength != validAttr.StringLength)
 83                         {
 84                             return "{0} 字段長度錯誤,長度必須為{1}".FormatWith(propName, validAttr.StringLength);
 85                         }
 86                         //校驗正則表達式
 87                         if (!validAttr.RegexpCheckFormat.IsNullOrEmptyOrWhiteSpace())
 88                         {
 89                             if (!Regex.IsMatch(propVal.ToString(), validAttr.RegexpCheckFormat))
 90                             {
 91                                 if (!validAttr.RegexpDisplayFormat.IsNull())
 92                                 {
 93                                     return "{0} 字段格式錯誤,正確格式為{1}".FormatWith(propName, validAttr.RegexpDisplayFormat);
 94                                 }
 95                                 else
 96                                 {
 97                                     return "{0} 字段格式錯誤".FormatWith(propName);
 98                                 }
 99                             }
100                         }
101                         //校驗集合
102                         if (propVal.IsInt32()
103                             && !validAttr.Int32Collection.IsNull()
104                             && !validAttr.Int32Collection.Contains(propVal.ToInt32()))
105                         {
106                             return "{0} 字段必須為 {1} 中的一個".FormatWith(propName, string.Join(",", validAttr.Int32Collection));
107                         }
108                         if (!validAttr.StringCollection.IsNull()
109                             && !validAttr.StringCollection.Contains(propVal.ToString()))
110                         {
111                             return "{0} 字段必須為 {1} 中的一個".FormatWith(propName, string.Join(",", validAttr.Int32Collection));
112                         }
113                     }
114                 }
115             }
116             return string.Empty;
117         }
118     }
View Code

demo:

有一個需要驗證的資源類:

技術分享
 1     public class ResourceDto
 2     {
 3         [Validate(ValidateType.IsDateTime, IsRequired = false)]
 4         public string ResoCreateTime { get; set; }
 5 
 6         [Validate(ValidateType.IsString, IsRequired = false)]
 7         public string ResoDesc { get; set; }
 8 
 9         [Validate(ValidateType.IsString, IsRequired = false)]
10         public string ResoId { get; set; }
11 
12         [Validate(ValidateType.IsBoolean, DisplayName = "是否顯示")]
13         public string ResoIsShow { get; set; }
14 
15         [Validate(ValidateType.IsString, DisplayName = "資源名稱")]
16         public string ResoName { get; set; }
17 
18         [Validate(ValidateType.IsInt32, DisplayName = "資源排序")]
19         public string ResoOrder { get; set; }
20 
21         [Validate(ValidateType.IsString, DisplayName = "父資源ID")]
22         public string ResoParentId { get; set; }
23 
24         [Validate(ValidateType.IsString, DisplayName = "資源類型")]
25         public string ResoType { get; set; }
26 
27         [Validate(ValidateType.IsDateTime, IsRequired = false)]
28         public string ResoUpdateTime { get; set; }
29 
30         [Validate(ValidateType.IsString, IsRequired = false)]
31         public string ResoUrl { get; set; }
32     }
View Code

控制器保存數據校驗部分:

技術分享
1                 ResourceDto model = new JavaScriptSerializer().Deserialize<ResourceDto>("FormData".ValueOfForm());
2 
3                 var checkResult = ValidateHandler.GetResultString(model);
4                 if (checkResult != string.Empty)
5                 {
6                     //以下是處理錯誤的代碼
7                     return;
8                 }
View Code

使用聲明式驗證,代碼有沒有簡潔美觀點?哈哈。

參數聲明式校驗