用过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. javascript数组遍历的几种常用方法性能分析对比

    前言: 数组遍历有很多种方法,虽然不同方法有不同的特性及适用环境,除了普通飞for循环之外,for...in能直接输出数组元素的索引,for...of能直接输出数组元素的值,map则可以直接生成新的数 ...

  2. ISO/IEC 9899:2011 条款3——术语、定义与符号

    3. 术语.定义与符号 1.对于此国际标准的意图,应用了以下定义.其它术语是在用斜体类型或一个语法规则左侧出现的地方定义.在本国际标准中所显式定义的术语不被假定为对其它地方所定义的类似术语的隐式引用. ...

  3. Anaconda3_5.3.1+Pycharm2018.3安装步骤

    最近更新了Anaconda软件,重新配置了以下Python开发环境,结果之前旧环境开发的好好的程序竟然跑不起来.网上各种搜索,各种找答案还是没有一篇靠谱的文章教我把问题解决.走了各种弯路,足足整了几天 ...

  4. MD5(3)

    import java.io.UnsupportedEncodingException; import java.security.PrivateKey; import java.security.S ...

  5. PAT 甲级 1080 Graduate Admission (30 分) (简单,结构体排序模拟)

    1080 Graduate Admission (30 分)   It is said that in 2011, there are about 100 graduate schools ready ...

  6. ubuntu中cmake版本升级

    在网上下载一个项目,编译提示版本太低 CMake Error at CMakeLists.txt: (cmake_minimum_required): CMake 编译方式安装(需要openssl) ...

  7. ServletRequest与HttpServletRequest

    ServletRequest 解析:代表来自客户端的请求.当Servlet容器接收到客户端的要求访问特定Servlet的请求时,容器先解析客户端的原始请求数据,把它包装成一个ServletReques ...

  8. [LeetCode] 583. Delete Operation for Two Strings 两个字符串的删除操作

    Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 t ...

  9. [转帖]Linux教程(13)- Linux中的通配符和正则表达式

    Linux教程(13)- Linux中的通配符和正则表达式 2018-08-22 06:16:44 钱婷婷 阅读数 39更多 分类专栏: Linux教程与操作 Linux教程与使用   版权声明:本文 ...

  10. day33——进程的创建方式、pid、空间隔离、join方法、其他属性、守护进程

    day33 进程创建的两种方式 在windows环境下,开启进程必须在______name______ == "______main______"下面 p.start(): 只是向 ...