用过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. flask 开发接口测试平台

    flask 开发接口测试平台 数据库,forms  views  视图, 数据库如下: # encoding: utf-8 ''' @author: lileilei @file: models.py ...

  2. java8之Spliterator

    基本用法: import java.util.Arrays; import java.util.Spliterator; import java.util.stream.IntStream; publ ...

  3. 【java爬虫】利用webmagic框架实战demo

    webmagic框架:http://webmagic.io/ WebMagic的结构分为Downloader.PageProcessor.Scheduler.Pipeline四大组件 PageProc ...

  4. 暚光科技定位系统数据解析-java

    暚光科技定位系统数据解析-java package com.ygkj.test; import java.io.DataInputStream; import java.io.IOException; ...

  5. tushare包使用案例

    Tushare是一个免费.开源的python财经数据接口包.主要实现对股票等金融数据从数据采集.清洗加工 到 数据存储的过程,能够为金融分析人员提供快速.整洁.和多样的便于分析的数据,为他们在数据获取 ...

  6. 【翻译】Flink Table Api & SQL —— 数据类型

    本文翻译自官网:https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/types.html Flink Table ...

  7. Axure中继器设置单选

    我们给元件添加组的名称是为了让软件知道哪些元件被放进了一个组中,然后软件会自动让这个组中只有一个元件能够是选中状态,以达到唯一被选中的效果.而中继器的这两个属性默认是启用的状态, 会把组的效果给取消, ...

  8. net::ERR_ABORTED 404 (Not Found)

    对于按需加载(on-demand-load)或加载外部资源(external resources)(如图片.文件等)来说,webpack的配置,output.publicPath是很重要的选项.如果指 ...

  9. [LeetCode] 165. Compare Version Numbers 比较版本数

    Compare two version numbers version1 and version1.If version1 > version2 return 1, if version1 &l ...

  10. 利用js来画图形(例如:条状图,圆饼图等)

    背景:java开发的过程中,需要对数据进行可视化,这样方便客户理解此时的数据状态 语言:java,js,window7,echarts包文件 sample的例子下面的参照 https://www.ec ...