.NET Attribute在資料校驗上的應用
阿新 • • 發佈:2020-05-13
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