C# 利用特性(Attribute)實現通用實體類數據合法校驗


用過asp.net mvc 的都應該知道,在實體類上添加一些特性,可以實現后端實體的數據校驗,這里簡單實現一下

實現原理:利用反射獲取實體的每一個屬性,並通過屬性獲取屬性上標注的特性,調用特性的Validate方法(此方法自定義的)來驗證屬性的值是否合法。

1、創建自己的校驗特性基類

此類繼承了Attribute,表明為一個特性,Validate方法為抽象方法,目的是給實現的子類自己定義自己的Validate方法。error為錯誤消息提示信息。

1 [AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
2     public abstract class BaseAttribute:Attribute
3     {
4         public virtual string error { get; set; }
5         public abstract bool Validate(object value);
6     }

2、創建特性類繼承自BaseAttribute

這里只簡單寫3個特性,寫法都一樣,只是校驗方法Validate中的邏輯不一樣。

 1 /// <summary>
 2     /// 約束屬性不能為空
 3     /// </summary>
 4     public class RequiredAttribute : BaseAttribute
 5     {
 6         public override string error {
 7             get
 8             {
 9                 if (base.error != null)
10                 {
11                     return base.error;
12                 }
13                 return "屬性不能為空";
14             }
15             set => base.error = value;
16         }
17         public override bool Validate(object value)
18         {
19             return !(value == null);
20         }
21     }
 1 /// <summary>
 2     /// 約束字符串的長度范圍
 3     /// </summary>
 4     public class StringRangeAttribute : BaseAttribute
 5     {
 6         public int min { get; set; }
 7         public int max { get; set; }
 8         public override string error {
 9             get {
10                 if (base.error != null)
11                 {
12                     return base.error;
13                 }
14                 return $"字符串長度范圍{this.min}-{this.max}";
15             }
16             set => base.error = value; }
17         public override bool Validate(object value)
18         {
19             return value.ToString().Length >= this.min && value.ToString().Length <= this.max;
20         }
21     }
 1 /// <summary>
 2     /// 約束符合正則表達式
 3     /// </summary>
 4     public class RegexAttribute : BaseAttribute
 5     {
 6         public string regexText;
 7         public override bool Validate(object value)
 8         {
 9             var regex = new Regex(regexText);
10             return regex.Match(value.ToString()).Success;
11         }
12     }

3、給實體類擴展一個方法,用來驗證實體類實例屬性值是否合法

此方式的擴展方法會污染其他非實體類,不是太推薦用太多此種擴展寫法,其實這里不寫成擴展方法也沒什么問題。

此擴展方法會驗證實例中的所有屬性,並將所有不通過驗證的屬性的提示信息以字符串的形式返回,所有都驗證通過則返回空串。

 1 public static string Validate<T>(this T t)
 2         {
 3             Type type = t.GetType();
 4 
 5             //獲取所有屬性
 6             PropertyInfo[] propertyInfos = type.GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
 7             List<string> errorList = new List<string>();
 8             foreach (PropertyInfo propertyInfo in propertyInfos)
 9             {
10                 if(propertyInfo.IsDefined(typeof(BaseAttribute)))//如果屬性上有定義該屬性,此步沒有構造出實例
11                 {
12                     foreach (BaseAttribute attribute in propertyInfo.GetCustomAttributes(typeof(BaseAttribute)))
13                     {
14                         if (!attribute.Validate(propertyInfo.GetValue(t, null)))
15                         {
16                             errorList.Add( $"[{propertyInfo.Name}]" + attribute.error);
17                         }
18                     }
19                     
20                 }
21             }
22             return string.Join(",", errorList);
23         }

4、定義一個實體類,並測試(控制台程序)。

假設有Student.cs ,在其id屬性中添加Required特性,name屬性上添加StringRange和Regex特性。

1 public class Student
2     {
3         [Required(error = "id 不能為空!")]
4         public int? id { get; set; }
5         [Regex(regexText = "^a.*a$",error = "屬性不合格規則")]
6         [StringRange(min =5,max =10)]
7         public string name { get; set; }
8     }
 1 static void Main(string[] args)
 2         {
 3             Student student = new Student()
 4             {
 5                 id = null,
 6                 name = "ajiudsagasgasgaxb"
 7             };
 8             string errorStr = student.Validate();
 9             Console.WriteLine(errorStr);
10             Console.ReadKey();
11         }

測試結果

 

此代碼純屬自己理解的原理性還原,代碼可能有多處寫的不嚴謹。


免責聲明!

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



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