C#Attribute 應用
阿新 • • 發佈:2021-10-29
特性應用
取得列舉型別的註釋
平時開發時,經常會用到列舉型別及其相關判斷,而有時我們想顯示列舉型別的註釋,怎麼辦?下面用特性來解決這個問題。
namespace AttributeDemo.CustomAttributes { public class RemarkAttribute : Attribute { private readonly string remark; public RemarkAttribute(string remark) { this.remark = remark; }public string GetRemark() { return remark; } } } namespace AttributeDemo.Extensions { public enum UserState { /// <summary> /// 正常 /// </summary> [RemarkAttribute("正常")] Normal = 0, /// <summary> /// 凍結 /// </summary> [RemarkAttribute("凍結")] Frozen, /// <summary> /// 刪除 /// </summary> [RemarkAttribute("刪除")] Deleted } public static class RemarkExtension { public static string GetRemark(this Enum value) { Type type = value.GetType(); FieldInfo field = type.GetField(value.ToString());if (field.IsDefined(typeof(RemarkAttribute), true)) { RemarkAttribute attr = field.GetCustomAttribute<RemarkAttribute>(); return attr.GetRemark(); } return value.ToString(); } } }
使用
UserState userState = UserState.Normal;
Console.WriteLine(userState.GetRemark());
資料有效性檢查
一般對於使用者提交的資料,我們都需要進行資料有效性的檢查,之後才能提交到資料庫。本次我們使用特性,優雅的解決這個問題。
宣告檢查資料長度的特性(因為想把資料校驗作為一個共通處理,因此需要首先宣告一個抽象類):
namespace AttributeDemo.CustomAttributes { public abstract class CustomValidateAttribute : Attribute { public abstract bool Validate(object value); } public class LengthValidateAttribute : CustomValidateAttribute { private readonly int minLen; private readonly int maxLen; public LengthValidateAttribute(int minLen, int maxLen) { this.minLen = minLen; this.maxLen = maxLen; } public override bool Validate(object value) { if (value != null && !string.IsNullOrEmpty(value.ToString())) { int len = value.ToString().Length; if (len >= minLen && len <= maxLen) { return true; } } return false; } } }
把特性附加到類中
namespace AttributeDemo { //可以對類整體使用 [CustomAttribute(description:"類特性示例",remark: "類特性")] public class Student { public int Id { get; set; } public string Name { get; set; } [LengthValidateAttribute(16, 100)]//追加對郵箱的長度檢查 public string EMail { get; set; } //可以對屬性欄位使用 [CustomAttribute(description: "屬性示例", remark: "屬性特性")] [LengthValidateAttribute(6, 9)]//追加對電話號碼的長度檢查 public string PhoneNumber { get; set; } //可以對方法使用 [CustomAttribute(description: "方法示例", remark: "方法特性")] public void Study() { Console.WriteLine($"{Name}正在學習中。。。"); } //可以對返回值使用 [return: CustomAttribute(description: "返回值示例", remark: "返回值特性")] public string SayHi([CustomAttribute(description: "引數示例", remark: "引數特性")] string name)//可以對引數列表使用 { return $"Hello {name}"; } } }
再對Student
類新增一個擴充套件方法(如果想對更廣泛範圍的物件進行資料校驗,可以對它們的基類追加擴充套件方法):
public static class ValidateExtension { public static bool Validate(this Student value) { int errCount = 0; Type type = value.GetType(); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo property in properties) { if (property.IsDefined(typeof(CustomValidateAttribute), true)) { IEnumerable<CustomValidateAttribute> attris = property.GetCustomAttributes<CustomValidateAttribute>(); foreach (CustomValidateAttribute attr in attris) { if (!attr.Validate(property.GetValue(value))) { Console.WriteLine($"資料校驗失敗:欄位[{property.Name}]"); errCount++; } } } } return errCount == 0 ? true : false; } }
呼叫資料校驗:
Student stu = new Student { Id = 1, EMail = "[email protected]", Name = "brein", PhoneNumber = "1234567890" }; stu.Validate();
輸出校驗結果:
程式設計是個人愛好資料校驗失敗:欄位[PhoneNumber] 資料校驗失敗:欄位[EMail]
以上,是兩個平時用的比較多的關於特性的應用場景。在ASP.NET Core
中,特性還有更多應用場景,例如:Filter
,Validate
,MVC
/API
相關特性,AOP
應用等等。可以說特性無處不在且非常重要。充分掌握特性相關知識,是掌握ASP.NET Core
的充分必要條件。