1. 程式人生 > >.NET Attribute在資料校驗上的應用

.NET Attribute在資料校驗上的應用

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); } } ``` 執行結果如下: ![](https://img2020.cnblogs.com/blog/1171637/202005/1171637-20200512225950643-1151892047.png) 從執行結果上看,我們拿到了我們想要的資料,那麼這個特性在實際使用過程中,到底有什麼用途呢? ### Attribute特性妙用 在實際開發過程中,我們的系統總會提供各種各樣的對外介面,其中引數的校驗是必不可少的一個環節。然而沒有特性時,校驗的程式碼是這樣的: ``` public class UserEntity { /// /// 姓名 /// [FieldDescription("使用者名稱稱")] public string Name { get; set; } /// /// 年齡 /// public int Age { get; set; } /// /// 地址 /// 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 { /// /// 校驗後的錯誤資訊 ///
public string ErrorMessage { get; set; } /// /// 資料校驗 /// /// public abstract void Validate(object value); } ``` 然後可以定義常用的一些對應的校驗Attribute,例如RequiredAttribute、StringLengthAttribute ``` /// /// 非空校驗 /// [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); } } } /// /// 自定義驗證,驗證字元長度 ///
[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 { /// /// 校驗 ///
/// /// public static void