1. 程式人生 > 其它 >最佳實踐_C#Api對接實體校驗

最佳實踐_C#Api對接實體校驗

工作之後,做過不少的api對接,有提供api介面,也有呼叫對方api介面。api對接中,實體校驗一定是必不可少的一個通用模組。

正常情況下,實體校驗通常包括:a 是否必填;b 資料型別;c 最大長度;d 取值範圍;e 集合最大數量。

這裡記錄下自己的最佳實踐,並作簡單解釋。

  1  public class DataValidateHelper
  2     {
  3         public static List<DataValidateResult> Validate<T>(T model)
  4         {
  5             var
result = new List<DataValidateResult>(); 6 var properties = model.GetType().GetProperties(); 7 foreach (var item in properties) 8 { 9 var ats = item.GetCustomAttribute(typeof(DataValidateAttribute), true) as DataValidateAttribute; 10
if (ats == null) 11 continue; 12 13 if (item.PropertyType.Equals(typeof(string))) 14 { 15 var v = Convert.ToString(item.GetValue(model)); 16 if (ats.Required && string.IsNullOrEmpty(v))
17 { 18 result.Add(new DataValidateResult(item.Name, v, ats.Message)); 19 continue; 20 } 21 22 if (!ats.Required && string.IsNullOrEmpty(v)) 23 continue; 24 25 if (ats.RegexString == null) 26 continue; 27 var regex = new Regex(ats.RegexString); 28 if (regex.IsMatch(v)) 29 continue; 30 31 result.Add(new DataValidateResult(item.Name, v, ats.Message)); 32 continue; 33 } 34 35 if (item.PropertyType.Equals(typeof(List<string>))) 36 { 37 var v = (List<string>)item.GetValue(model); 38 if (ats.Required && (v == null || v.Count == 0)) 39 { 40 result.Add(new DataValidateResult(item.Name, "null", ats.Message)); 41 continue; 42 } 43 44 if (!ats.Required && (v == null || v.Count == 0)) 45 continue; 46 47 if (ats.MaxListCount > 0 && ats.MaxListCount < v.Count) 48 { 49 result.Add(new DataValidateResult(item.Name, v.Count.ToString(), ats.Message)); 50 continue; 51 } 52 53 if (ats.RegexString == null) 54 continue; 55 foreach (var children in v) 56 { 57 var regex = new Regex(ats.RegexString); 58 if (regex.IsMatch(children)) 59 continue; 60 61 result.Add(new DataValidateResult(item.Name, children, ats.Message)); 62 } 63 continue; 64 } 65 66 if (item.PropertyType.IsClass) 67 { 68 if (item.PropertyType.IsGenericType) 69 { 70 var v = item.GetValue(model) as IEnumerable<object>; 71 if (ats.Required && (v == null || v.Count() == 0)) 72 { 73 result.Add(new DataValidateResult(item.Name, "null", ats.Message)); 74 continue; 75 } 76 77 if (!ats.Required && (v == null || v.Count() == 0)) 78 continue; 79 80 if (ats.MaxListCount > 0 && ats.MaxListCount < v.Count()) 81 { 82 result.Add(new DataValidateResult(item.Name, v.Count().ToString(), ats.Message)); 83 continue; 84 } 85 86 foreach (var children in v) 87 { 88 result.AddRange(Validate(children)); 89 } 90 continue; 91 } 92 93 var va = item.GetValue(model); 94 if (ats.Required && va == null) 95 { 96 result.Add(new DataValidateResult(item.Name, "null", ats.Message)); 97 continue; 98 } 99 100 if (!ats.Required && va == null) 101 continue; 102 103 result.AddRange(Validate(va)); 104 } 105 } 106 107 return result; 108 } 109 } 110 111 public class DataValidateResult 112 { 113 public string CoulumnName { get; set; } 114 public string CoulumnValue { get; set; } 115 public string ErroMessage { get; set; } 116 117 public DataValidateResult(string columnName, string coulumnValue, string erroMessage) 118 { 119 CoulumnName = columnName; 120 CoulumnValue = coulumnValue; 121 ErroMessage = erroMessage; 122 } 123 } 124 125 public class DataValidateAttribute : Attribute 126 { 127 public bool Required { get; set; } 128 public string RegexString { get; set; } 129 public int MaxListCount { get; set; } 130 public string Message { get; set; } 131 }
View Code

簡單解釋下

1 實體內欄位資料型別共4中:string型別;List<string>型別;T型別;List<T>型別。最小顆粒度當然就是string,避免一些預設值不是null的資料型別,因預設值引起的實際值變化。

2 通過欄位特性設定校驗,Required:是否必填;MaxListCount:集合最大數量;RegexString:其餘校驗通過正則表示式體現;Message:自定義校驗失敗提示。

3 欄位校驗結果List<DataValidateResult>,所有校驗失敗的資訊在該集合內體現,欄位名/當前值/失敗提示資訊。至於api怎麼展現和使用這些校驗結果,根絕返回結果自己拼裝。

4 整個校驗邏輯的主題思想是:通過反射和遞迴出作為最小顆粒度的每個欄位,並將其值和通過特性設定的限制條件對比,如果不符合則視為校驗失敗,並返回失敗資訊。