C# 利用特性(Attribute)实现通用实体类数据合法校验
用过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)实现通用实体类数据合法校验的更多相关文章
- 利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理
		在我们开发Web API应用的时候,我们可以借鉴ABP框架的过滤器Filter和特性Attribute的应用,实现对Web API返回结果的封装和统一异常处理,本篇随笔介绍利用AuthorizeAtt ... 
- C#开发---利用特性自定义数据导出到Excel
		网上C#导出Excel的方法有很多.但用来用去感觉不够自动化.于是花了点时间,利用特性做了个比较通用的导出方法.只需要根据实体类,自动导出想要的数据 1.在NuGet上安装Aspose.Cells或 ... 
- C# 特性(Attribute)(一)
		特性(Attributes)是一种崭新的声明性信息.我们不仅可以通过特性来定义设计层面的信息(例如help file, URL for documentation)以及运行时(run-time)信息( ... 
- 特性attribute,声明和使用attribute,应用attribute,AOP面向切面,多种方式实现AOP
		1 特性attribute,和注释有什么区别2 声明和使用attribute3 应用attribute4 AOP面向切面5 多种方式实现AOP ---------------------------- ... 
- [C#] 剖析 AssemblyInfo.cs - 了解常用的特性 Attribute
		剖析 AssemblyInfo.cs - 了解常用的特性 Attribute [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5944391.html 序 ... 
- [C#] C# 知识回顾 - 特性 Attribute
		C# 知识回顾 - 特性 Attribute [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5911289.html 目录 特性简介 使用特性 特性 ... 
- C# 知识特性 Attribute
		C#知识--获取特性 Attribute 特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联.特性与程序实体关联后,可在运行时使用"反射"查询 ... 
- .Net内置特性Attribute介绍
		特性Attribute概述 特性(Attribute)是一种特殊的类型,可以加载到程序集或者程序集的类型上,这些类型包括模块.类.接口.结构.构造函数.方法.字段等,加载了特性的类型称之为特性的目标. ... 
- 【C#进阶系列】18 特性Attribute
		这个东西有的叫定制特性,然而我喜欢直接叫特性,但是这样的话一些人不知道我说的是什么,如果我说是Attribute的话那么知道的或者用过的就都懂了. 还记得讲到枚举和位标志那一章,关于位标志,有一个[F ... 
随机推荐
- Calcite分析 - RelTrait
			RelTrait 表示RelNode的物理属性 由RelTraitDef代表RelTrait的类型 /** * RelTrait represents the manifestation of a r ... 
- 数据分析之--log文件自动化分析
			https://mp.weixin.qq.com/s?__biz=MjM5NjE2MTIyMw==&mid=2257483803&idx=1&sn=efe24b040397cd ... 
- Aspect切面的使用实例
			一.导入切面库 以maven工程为例,除了springmvc基础的库,需要导入切面库,本例aspectj为例. <properties> <aspectj.version>&l ... 
- Hadoop记录-Apache hadoop+spark集群部署
			Hadoop+Spark集群部署指南 (多节点文件分发.集群操作建议salt/ansible) 1.集群规划节点名称 主机名 IP地址 操作系统Master centos1 192.168.0.1 C ... 
- OutOfMemoryError异常——Java堆溢出。
			https://blog.csdn.net/en_joker/article/details/79726975 (将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数- ... 
- 基于EasyDarwin开源流媒体服务器框架实现EasyNVR H5无插件直播流媒体服务器方案
			背景分析 在之前的一篇博客<web无插件播放RTSP摄像机方案,拒绝插件,拥抱H5!>中,描述了实现一套H5无插件直播方案的各个组件的参考建议,又在博客<EasyNVR H5流媒体服 ... 
- NLP理解层次 --- 思维导图
- 【VS开发】Visual C++内存泄露检测—VLD工具使用说明
			Visual C++内存泄露检测-VLD工具使用说明 一. VLD工具概述 Visual Leak Detector(VLD)是一款用于Visual C++的免费的内存泄露检测工具.他的 ... 
- 【C/C++开发】C++实现字符串替换的两种方法
			替换字符串replace() erase() //C++ 第一种替换字符串的方法用replace()|C++ 第二种替换字符串的方法用erase()和insert()[ C++string|C++ r ... 
- 托马斯·贝叶斯 (Thomas Bayes)
			朴素贝叶斯 Day15,开始学习朴素贝叶斯,先了解一下贝爷,以示敬意. 托马斯·贝叶斯 (Thomas Bayes),英国神学家.数学家.数理统计学家和哲学家,1702年出生于英国伦敦,做过神甫: ... 
