关于.NET Attribute在数据校验中的应用教程
 更新时间:2020年05月13日 08:45:27   作者:hexuwsbg  

这篇文章主要给大家介绍了关于.NET Attribute在数据校验中的应用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用.NET具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言
Attribute(特性)的概念不在此赘述了,相信有点.NET基础的开发人员都明白,用过Attribute的人也不在少数,毕竟很多框架都提供自定义的属性,类似于Newtonsoft.JSON中JsonProperty、JsonIgnore等
自定义特性
.NET 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。
创建并使用自定义特性包含四个步骤:

声明自定义特性
构建自定义特性
在目标程序元素上应用自定义特性
通过反射访问特性

声明自定义特性
一个新的自定义特性必须派生自System.Attribute类,例如:

public class FieldDescriptionAttribute : Attribute
{
public string Description { get; private set; }

public FieldDescriptionAttribute(string description)
{
Description = description;
}
}

public class UserEntity
{
[FieldDescription(“用户名称”)]
public string Name { get; set; }
}

该如何拿到我们标注的信息呢?这时候需要使用反射获取

var type = typeof(UserEntity);
var properties = type.GetProperties();
foreach (var item in properties)
{
if(item.IsDefined(typeof(FieldDescriptionAttribute), true))
{
var attribute = item.GetCustomAttribute(typeof(FieldDescriptionAttribute)) as FieldDescriptionAttribute;
Console.WriteLine(attribute.Description);
}
}

执行结果如下:

从执行结果上看,我们拿到了我们想要的数据,那么这个特性在实际使用过程中,到底有什么用途呢?
Attribute特性妙用
在实际开发过程中,我们的系统总会提供各种各样的对外接口,其中参数的校验是必不可少的一个环节。然而没有特性时,校验的代码是这样的:

public class UserEntity
{
/// <summary>
/// 姓名
/// </summary>
[FieldDescription(“用户名称”)]
public string Name { get; set; }

/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }

/// <summary>
/// 地址
/// </summary>
public string Address { get; set; }
}

UserEntity user = new UserEntity();

if (string.IsNullOrWhiteSpace(user.Name))
{
throw new Exception(“姓名不能为空”);
}
if (user.Age <= 0)
{
throw new Exception(“年龄不合法”);
}
if (string.IsNullOrWhiteSpace(user.Address))
{
throw new Exception(“地址不能为空”);
}

字段多了之后这种代码就看着非常繁琐,并且看上去不直观。对于这种繁琐又恶心的代码,有什么方法可以优化呢?
使用特性后的验证写法如下:
首先定义一个基础的校验属性,提供基础的校验方法

public abstract class AbstractCustomAttribute : Attribute
{
/// <summary>
/// 校验后的错误信息
/// </summary>
public string ErrorMessage { get; set; }

/// <summary>
/// 数据校验
/// </summary>
/// <param name=”value”></param>
public abstract void Validate(object value);
}

然后可以定义常用的一些对应的校验Attribute,例如RequiredAttribute、StringLengthAttribute

/// <summary>
/// 非空校验
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : AbstractCustomAttribute
{
public override void Validate(object value)
{
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
throw new Exception(string.IsNullOrWhiteSpace(ErrorMessage) ? “字段不能为空” : ErrorMessage);
}
}
}

/// <summary>
/// 自定义验证,验证字符长度
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class StringLengthAttribute : AbstractCustomAttribute
{
private int _maxLength;
private int _minLength;

public StringLengthAttribute(int minLength, int maxLength)
{
this._maxLength = maxLength;
this._minLength = minLength;
}

public override void Validate(object value)
{
if (value != null && value.ToString().Length >= _minLength && value.ToString().Length <= _maxLength)
{
return;
}

throw new Exception(string.IsNullOrWhiteSpace(ErrorMessage) ? $”字段长度必须在{_minLength}与{_maxLength}之间” : ErrorMessage);
}
}

添加一个用于校验的ValidateExtensions

public static class ValidateExtensions
{
/// <summary>
/// 校验
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <returns></returns>
public static void Validate<T>(this T entity) where T : class
{
Type type = entity.GetType();

foreach (var item in type.GetProperties())
{
//需要对Property的字段类型做区分处理针对Object List 数组需要做区分处理
if (item.PropertyType.IsPrimitive || item.PropertyType.IsEnum || item.PropertyType.IsValueType || item.PropertyType == typeof(string))
{
//如果是基元类型、枚举类型、值类型或者字符串 直接进行校验
CheckProperty(entity, item);
}
else
{
//如果是引用类型
var value = item.GetValue(entity, null);
CheckProperty(entity, item);
if (value != null)
{
if ((item.PropertyType.IsGenericType && Array.Exists(item.PropertyType.GetInterfaces(), t => t.GetGenericTypeDefinition() == typeof(IList<>))) || item.PropertyType.IsArray)
{
//判断IEnumerable
var enumeratorMI = item.PropertyType.GetMethod(“GetEnumerator”);
var enumerator = enumeratorMI.Invoke(value, null);
var moveNextMI = enumerator.GetType().GetMethod(“MoveNext”);
var currentMI = enumerator.GetType().GetProperty(“Current”);
int index = 0;
while (Convert.ToBoolean(moveNextMI.Invoke(enumerator, null)))
{
var currentElement = currentMI.GetValue(enumerator, null);
if (currentElement != null)
{
currentElement.Validate();
}
index++;
}
}
else
{
value.Validate();
}
}
}
}
}

private static void CheckProperty(object entity, PropertyInfo property)
{
if (property.IsDefined(typeof(AbstractCustomAttribute), true))//此处是重点
{
//此处是重点
foreach (AbstractCustomAttribute attribute in property.GetCustomAttributes(typeof(AbstractCustomAttribute), true))
{
if (attribute == null)
{
throw new Exception(“AbstractCustomAttribute not instantiate”);
}

attribute.Validate(property.GetValue(entity, null));
}
}
}
}

新的实体类

public class UserEntity
{
/// <summary>
/// 姓名
/// </summary>
[Required]
public string Name { get; set; }

/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }

/// <summary>
/// 地址
/// </summary>
[Required]
public string Address { get; set; }

[StringLength(11, 11)]
public string PhoneNum { get; set; }
}

调用方式

UserEntity user = new UserEntity();
user.Validate();

上面的校验逻辑写的比较复杂,主要是考虑到对象中包含复杂对象的情况,如果都是简单对象,可以不用考虑,只需针对单个属性做字段校验
现有的方式是在校验不通过的时候抛出异常,此处大家也可以自定义异常来表示校验的问题,也可以返回自定义的校验结果实体来记录当前是哪个字段出的问题,留待大家自己实现
如果您有更好的建议和想法欢迎提出,共同进步
总结
到此这篇关于.NET Attribute在数据校验中的应用的文章就介绍到这了,更多相关.NET Attribute在数据校验的应用内容请搜索华域联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持华域联盟!

您可能感兴趣的文章:详解.Net Core 权限验证与授权(AuthorizeFilter、ActionFilterAttribute)ASP.NET MVC使用ActionFilterAttribute实现权限限制的方法(附demo源码下载).NET获取枚举DescriptionAttribute描述信息性能改进的多种方法asp.net MVC利用ActionFilterAttribute过滤关键字的方法

.net
attribute
校验

相关文章
ASP.NET web.config中 数据库连接字符串加密解密本文主要介绍利用aspnet_regiis.exe工具对web.config中connectionStrings节点进行加密和解密的过程,希望对大家有所帮助。 2016-05-05
.net搜索查询并实现分页实例.net搜索查询并实现分页实例,需要的朋友可以参考一下 2013-03-03
将DataTable中的一行复制到另一个DataTable的方法将DataTable中的一行复制到另一个DataTable的方法… 2007-09-09
在后台cs中调用js中示例cs中调用js中的方法有很多,不过比较使用的就那么几个,下面为大家介绍下ScriptManager.RegisterStartupScript方法的使用 2013-10-10
Asp.Net用OWC操作Excel的实例代码这篇文章介绍了Asp.Net用OWC操作Excel的实例代码,有需要的朋友可以参考一下,希望对你有所帮助 2013-07-07
asp.net 2.0中利用Ajax2.0实现JSON传送大量页面数据本人遇到一个程序页面,要有很大量的数据进行交互操作。 2010-03-03
asp.net实现上传图片时判断图片的模式GRB或CMYK的方法这篇文章主要介绍了asp.net实现上传图片时判断图片的模式GRB或CMYK的方法,涉及asp.net针对图片的读取及属性操作相关技巧,需要的朋友可以参考下 2016-07-07
在SQL Server中使用CLR调用.NET方法实现思路在.NET中新建一个类,并在这个类里新建一个方法,然后在SQL Server中调用这个方法,接下来我们将实现这个功能做了以下几个步骤,详细看下本文,感兴趣的你可不要错过了哈 2013-02-02
详解如何在ASP.NET Core中编写高效的控制器这篇文章主要介绍了详解如何在ASP.NET Core中编写高效的控制器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 2021-02-02
ASP.NET Mvc开发之EF延迟加载ASP.NET Mvc开发之EF延迟加载,到底什么是EF的延迟加载呢?这篇文章我们就来看看 2016-02-02

最新评论

声明:本站(华域联盟www.cnhackhy.com)所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。