C# 利用特性(Attribute)实现通用实体类数据合法校验

时间:2019-08-21
本文章向大家介绍C# 利用特性(Attribute)实现通用实体类数据合法校验,主要包括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         }

测试结果

此代码纯属自己理解的原理性还原,代码可能有多处写的不严谨。

原文地址:https://www.cnblogs.com/fnz0/p/11387835.html