用过asp.net mvc 的都应该知道,在实体类上添加一些特性,可以实现后端实体的数据校验,这里简单实现一下

实现原理:利用反射获取实体的每一个属性,并通过属性获取属性上标注的特性,调用特性的Validate方法(此方法自定义的)来验证属性的值是否合法。

1、创建自己的校验特性基类

此类继承了Attribute,表明为一个特性,Validate方法为抽象方法,目的是给实现的子类自己定义自己的Validate方法。error为错误消息提示信息。

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

2、创建特性类继承自BaseAttribute

这里只简单写3个特性,写法都一样,只是校验方法Validate中的逻辑不一样。

 /// <summary>
/// 约束属性不能为空
/// </summary>
public class RequiredAttribute : BaseAttribute
{
public override string error {
get
{
if (base.error != null)
{
return base.error;
}
return "属性不能为空";
}
set => base.error = value;
}
public override bool Validate(object value)
{
return !(value == null);
}
}
 /// <summary>
/// 约束字符串的长度范围
/// </summary>
public class StringRangeAttribute : BaseAttribute
{
public int min { get; set; }
public int max { get; set; }
public override string error {
get {
if (base.error != null)
{
return base.error;
}
return $"字符串长度范围{this.min}-{this.max}";
}
set => base.error = value; }
public override bool Validate(object value)
{
return value.ToString().Length >= this.min && value.ToString().Length <= this.max;
}
}
 /// <summary>
/// 约束符合正则表达式
/// </summary>
public class RegexAttribute : BaseAttribute
{
public string regexText;
public override bool Validate(object value)
{
var regex = new Regex(regexText);
return regex.Match(value.ToString()).Success;
}
}

3、给实体类扩展一个方法,用来验证实体类实例属性值是否合法

此方式的扩展方法会污染其他非实体类,不是太推荐用太多此种扩展写法,其实这里不写成扩展方法也没什么问题。

此扩展方法会验证实例中的所有属性,并将所有不通过验证的属性的提示信息以字符串的形式返回,所有都验证通过则返回空串。

 public static string Validate<T>(this T t)
{
Type type = t.GetType(); //获取所有属性
PropertyInfo[] propertyInfos = type.GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
List<string> errorList = new List<string>();
foreach (PropertyInfo propertyInfo in propertyInfos)
{
if(propertyInfo.IsDefined(typeof(BaseAttribute)))//如果属性上有定义该属性,此步没有构造出实例
{
foreach (BaseAttribute attribute in propertyInfo.GetCustomAttributes(typeof(BaseAttribute)))
{
if (!attribute.Validate(propertyInfo.GetValue(t, null)))
{
errorList.Add( $"[{propertyInfo.Name}]" + attribute.error);
}
} }
}
return string.Join(",", errorList);
}

4、定义一个实体类,并测试(控制台程序)。

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

 public class Student
{
[Required(error = "id 不能为空!")]
public int? id { get; set; }
[Regex(regexText = "^a.*a$",error = "属性不合格规则")]
[StringRange(min =,max =)]
public string name { get; set; }
}
 static void Main(string[] args)
{
Student student = new Student()
{
id = null,
name = "ajiudsagasgasgaxb"
};
string errorStr = student.Validate();
Console.WriteLine(errorStr);
Console.ReadKey();
}

测试结果

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

C# 利用特性(Attribute)实现通用实体类数据合法校验的更多相关文章

  1. 利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理

    在我们开发Web API应用的时候,我们可以借鉴ABP框架的过滤器Filter和特性Attribute的应用,实现对Web API返回结果的封装和统一异常处理,本篇随笔介绍利用AuthorizeAtt ...

  2. C#开发---利用特性自定义数据导出到Excel

    网上C#导出Excel的方法有很多.但用来用去感觉不够自动化.于是花了点时间,利用特性做了个比较通用的导出方法.只需要根据实体类,自动导出想要的数据  1.在NuGet上安装Aspose.Cells或 ...

  3. C# 特性(Attribute)(一)

    特性(Attributes)是一种崭新的声明性信息.我们不仅可以通过特性来定义设计层面的信息(例如help file, URL for documentation)以及运行时(run-time)信息( ...

  4. 特性attribute,声明和使用attribute,应用attribute,AOP面向切面,多种方式实现AOP

    1 特性attribute,和注释有什么区别2 声明和使用attribute3 应用attribute4 AOP面向切面5 多种方式实现AOP ---------------------------- ...

  5. [C#] 剖析 AssemblyInfo.cs - 了解常用的特性 Attribute

    剖析 AssemblyInfo.cs - 了解常用的特性 Attribute [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5944391.html 序 ...

  6. [C#] C# 知识回顾 - 特性 Attribute

    C# 知识回顾 - 特性 Attribute [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5911289.html 目录 特性简介 使用特性 特性 ...

  7. C# 知识特性 Attribute

    C#知识--获取特性 Attribute 特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联.特性与程序实体关联后,可在运行时使用"反射"查询 ...

  8. .Net内置特性Attribute介绍

    特性Attribute概述 特性(Attribute)是一种特殊的类型,可以加载到程序集或者程序集的类型上,这些类型包括模块.类.接口.结构.构造函数.方法.字段等,加载了特性的类型称之为特性的目标. ...

  9. 【C#进阶系列】18 特性Attribute

    这个东西有的叫定制特性,然而我喜欢直接叫特性,但是这样的话一些人不知道我说的是什么,如果我说是Attribute的话那么知道的或者用过的就都懂了. 还记得讲到枚举和位标志那一章,关于位标志,有一个[F ...

随机推荐

  1. v-if和v-for一起使用的几个方法

    方法一(推荐): 不带if <ul> <li v-for="(item, index) in list" :key="index" > ...

  2. USB:USB通信中的端点(endpoint)和四种传输模式

    USB的传输模式有4种,分别是控制传输(Control Transfer).中断传输(Interrupt Transfer).批量传输或叫块传输(Bulk Transfer).实时传输或叫同步传输(I ...

  3. ActiveMQ消息中间件的作用以及应用场景

    ActiveMQ消息中间件的作用以及应用场景 一.ActiveMQ简介 ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ是一个完全支持JMS1.1和J2EE1.4 ...

  4. osg::Node位置移动

    osg::Node节点移动的时候,可以使用osg::Matrix::translate  来完成 osg::Matrix::translate中的参数是  当前位置到目标位置需要改变的值,所以,传递参 ...

  5. SpringCloud基础知识

    什么是SpringCloud Spring Cloud是一系列框架的有序集合. 为什么用SpringCloud Spring Cloud涵盖面广,能够与Spring Framework.Spring ...

  6. vue的mixin简化开发

    vue的mixin可以将多个组件公用的声明周期方法和数据封装成一个对象,在不同的组件中自由插拔.实际做项目的时候,可以定义一些mixin,供多个组件使用.也非常有必要定义一个全局的mixin对象,对所 ...

  7. python语言使用yaml 管理selenium元素

    1.所有元素都在PageElement下的.yaml,如图 login_page.yaml文件: username: dec: 登录页 type: xpath value: //input[@clas ...

  8. UIView的intrinsicContentSize方法,在按钮中重写

    场景,一个有图片有文字的按钮在其父控件上加了上左的约束,然后,有需要要调整按钮与图片之间的间距,第一想法就是设置title insets 的left. 然后问题出现了,这个按钮的文字居然显示不全了,也 ...

  9. kubernetes核心原理之API Server原理分析

    kubernetes API Server的核心功能是提供了Kubernetes各类资源对象(Pod,RC,Service等)的增删改查及Watch等HTTP Rest接口,成为集群内各个功能模块之间 ...

  10. [LeetCode] 229. Majority Element II 多数元素 II

    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. Note: The a ...