如何在.NET中利用Attribute對數(shù)據(jù)進(jìn)行校驗(yàn)?針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
創(chuàng)新互聯(lián)主要從事成都網(wǎng)站建設(shè)、成都做網(wǎng)站、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)芝罘,10多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575前言
Attribute(特性)的概念不在此贅述了,相信有點(diǎn).NET基礎(chǔ)的開發(fā)人員都明白,用過Attribute的人也不在少數(shù),畢竟很多框架都提供自定義的屬性,類似于Newtonsoft.JSON中JsonProperty、JsonIgnore等
自定義特性
.NET 框架允許創(chuàng)建自定義特性,用于存儲聲明性的信息,且可在運(yùn)行時被檢索。該信息根據(jù)設(shè)計標(biāo)準(zhǔn)和應(yīng)用程序需要,可與任何目標(biāo)元素相關(guān)。
創(chuàng)建并使用自定義特性包含四個步驟:
聲明自定義特性
構(gòu)建自定義特性
在目標(biāo)程序元素上應(yīng)用自定義特性
通過反射訪問特性
聲明自定義特性
一個新的自定義特性必須派生自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; } }
該如何拿到我們標(biāo)注的信息呢?這時候需要使用反射獲取
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); } }
執(zhí)行結(jié)果如下:
從執(zhí)行結(jié)果上看,我們拿到了我們想要的數(shù)據(jù),那么這個特性在實(shí)際使用過程中,到底有什么用途呢?
Attribute特性妙用
在實(shí)際開發(fā)過程中,我們的系統(tǒng)總會提供各種各樣的對外接口,其中參數(shù)的校驗(yàn)是必不可少的一個環(huán)節(jié)。然而沒有特性時,校驗(yàn)的代碼是這樣的:
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("地址不能為空"); }
字段多了之后這種代碼就看著非常繁瑣,并且看上去不直觀。對于這種繁瑣又惡心的代碼,有什么方法可以優(yōu)化呢?
使用特性后的驗(yàn)證寫法如下:
首先定義一個基礎(chǔ)的校驗(yàn)屬性,提供基礎(chǔ)的校驗(yàn)方法
public abstract class AbstractCustomAttribute : Attribute { /// <summary> /// 校驗(yàn)后的錯誤信息 /// </summary> public string ErrorMessage { get; set; } /// <summary> /// 數(shù)據(jù)校驗(yàn) /// </summary> /// <param name="value"></param> public abstract void Validate(object value); }
然后可以定義常用的一些對應(yīng)的校驗(yàn)Attribute,例如RequiredAttribute、StringLengthAttribute
/// <summary> /// 非空校驗(yàn) /// </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> /// 自定義驗(yàn)證,驗(yàn)證字符長度 /// </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); } }
添加一個用于校驗(yàn)的ValidateExtensions
public static class ValidateExtensions { /// <summary> /// 校驗(yàn) /// </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的字段類型做區(qū)分處理針對Object List 數(shù)組需要做區(qū)分處理 if (item.PropertyType.IsPrimitive || item.PropertyType.IsEnum || item.PropertyType.IsValueType || item.PropertyType == typeof(string)) { //如果是基元類型、枚舉類型、值類型或者字符串 直接進(jìn)行校驗(yàn) 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))//此處是重點(diǎn) { //此處是重點(diǎn) foreach (AbstractCustomAttribute attribute in property.GetCustomAttributes(typeof(AbstractCustomAttribute), true)) { if (attribute == null) { throw new Exception("AbstractCustomAttribute not instantiate"); } attribute.Validate(property.GetValue(entity, null)); } } } }
新的實(shí)體類
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; } }
調(diào)用方式
UserEntity user = new UserEntity(); user.Validate();
關(guān)于如何在.NET中利用Attribute對數(shù)據(jù)進(jìn)行校驗(yàn)問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。
文章標(biāo)題:如何在.NET中利用Attribute對數(shù)據(jù)進(jìn)行校驗(yàn)-創(chuàng)新互聯(lián)
鏈接分享:http://www.rwnh.cn/article18/pdddp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、靜態(tài)網(wǎng)站、小程序開發(fā)、手機(jī)網(wǎng)站建設(shè)、App開發(fā)、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容