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 ...
随机推荐
- Oracle系列十二 约束
约束是表级的强制规定有以下五种约束: NOT NULL UNIQUE PRIMARY KEY FOREIGN KEY CHECK 注意事项 如果不指定约束名 ,Oracle server 自动按照 S ...
- Spark资源调度及任务调度
1. 资源分配 通过SparkSubmit进行提交应用后,首先会创建Client将应用程序(字节码文件.class)包装成Driver,并将其注册到Master.Master收到Client的注册请 ...
- 安装TensorFlow后import tensorflow时,出现CXXABI_1.3.11和GLIBCXX_3.4.22 not found
Ubuntu16.04使用Anaconda搭建TensorFlow使用环境但是在安装TensorFlow后,import tensorflow报出如下错误: 该问题的错误原因是由于gcc的动态库较老导 ...
- SpringCloud中遇到的问题总结
1.如果数据库URL字符串中不加serverTimezone=GMT%2B8且数据库未设置时区,会报如下错误 Caused by: com.mysql.cj.exceptions.InvalidCon ...
- Docker安装ES和Kibana
1.ES安装 1.下载ES镜像问题 docker pull elasticsearch 2.运行ES docker run -it --name elasticsearch -d -p 9200:92 ...
- Linux下 PostgrelSQL 基本操作
一.在默认配置条件下,本机访问PostgreSQL 切换到Linux用户postgres,然后执行psql: $ su - postgres Last login: Wed Mar 1 13:16:4 ...
- php中类的不定参数使用示例
在类的实例化过程中,可以带或不带参数,那么构造函数将如何处理这些参数呢?为了使构造函数具有通用性,在定义构造函数时,一般不带参数,然后在其内部对参数情况进行处理.下面代码显示了一个完整的通用Perso ...
- [LeetCode] 127. Word Ladder 单词阶梯
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest t ...
- [LeetCode] 216. Combination Sum III 组合之和 III
Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...
- Kubernetes 配置管理 Dashboard(十三)
目录 一.安装配置 1.1 下载 镜像 1.2.安装 1.3.修改 NodePort 二.配置授权 Kubernetes 所有的操作我们都是通过命令行工具 kubectl 完成的.为了提供更丰富的用户 ...