參數聲明式校驗
阿新 • • 發佈:2017-07-27
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 = 50000View Code, 8 }
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;View Code10 //字段指定長度 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 }
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
使用聲明式驗證,代碼有沒有簡潔美觀點?哈哈。
參數聲明式校驗