1.特性的任務:特性就是為了支持對象添加一些自我描述的信息,不影響類封裝的前提添加額外信息。如果你用這個信息,那特性就有用;如果你不需要這個信息,那么這個特性就沒用。
2.特性的基類:Attribute。例如:Obsolete特性,提出警告信息或錯誤信息,特性可以影響編譯、影響運行。
3.特性類通常用Attribute結尾,在使用的時候可以用全稱,也可以去掉這個結尾,也可以加上小括號顯示調用構造函數,如果不加小括號默認調用無參構造函數,也可以在括號內直接給屬性或字段賦值。
4.特性往往只能修飾一個對象一次,需要設置屬性的屬性的時候,需要給屬性添加AttributeUsage屬性,可以用來設置:是否允許多次修飾、修飾對象的類別(類or字段等)
5.DLL文件=IL中間語言+metadata元數據,特性信息會被編譯到元數據中。
6.使用場景
6.1為類或成員添加描述信息,然后在使用的時候拿到該信息。
/// <summary> /// 描述實體映射的數據表 /// </summary> public class TableNameAttribute : Attribute { public TableNameAttribute() { } public string TableName { get; set; } } [TableName(TableName = "Users")] public class User { public int Id { get; set; } public string Name { get; set; } } class Program { public static void Main(string[] args) { User user = new User(); Type t = user.GetType(); object[] customAttrs = t.GetCustomAttributes(true); for (int i = 0; i < customAttrs.Length; i++) { if (customAttrs[i] is TableNameAttribute) { TableNameAttribute tnAttr = (TableNameAttribute)customAttrs[i]; Console.WriteLine(tnAttr.TableName); } } } }
6.2 做數據驗證
public class IntValidateAttribute : Attribute { /// <summary> /// 最小值 /// </summary> private int minValue { get; set; } /// <summary> /// 最大值 /// </summary> private int maxValue { get; set; } /// <summary> /// 構造函數 /// </summary> /// <param name="minValue"></param> /// <param name="maxValue"></param> public IntValidateAttribute(int minValue, int maxValue) { this.minValue = minValue; this.maxValue = maxValue; } /// <summary> /// 檢驗值是否合法 /// </summary> /// <param name="checkValue"></param> /// <returns></returns> public bool Validate(int checkValue) { return checkValue >= minValue && checkValue <= maxValue; } } public class User { [IntValidate(1, 10)] public int Id { get; set; } public string Name { get; set; } } public class BaseDal { public static string Insert<T>(T model) { Type modelType = typeof(T); //獲取類型的所有屬性 PropertyInfo[] propertyInfos = modelType.GetProperties(); bool boIsCheck = true; //循環所有屬性 foreach (var property in propertyInfos) { //獲取屬性的所有特性 object[] attrs = property.GetCustomAttributes(true); if (property.PropertyType.Name.ToLower().Contains("int")) { foreach (var attr in attrs) { if (attr is IntValidateAttribute) { IntValidateAttribute intValidate = (IntValidateAttribute)attr; //執行特性的驗證邏輯 boIsCheck = intValidate.Validate((int)property.GetValue(model)); } } } if (!boIsCheck) { break; } } if (boIsCheck) { return "驗證通過,插入數據庫成功"; } else { return "驗證失敗"; } } } class Program { public static void Main(string[] args) { string msg = BaseDal.Insert<User>(new User() { Id = 123, Name = "lvcc" }); Console.WriteLine(msg); } }
6.3 添加說明信息並獲取,同6.1
/// <summary> /// 備注特性 /// </summary> public class RemarkAttribute : Attribute { private string Remark { get; set; } public RemarkAttribute(string Remark) { this.Remark = Remark; } public string GetRemark() { return this.Remark; } } public enum ESex { [Attributes.Remark("男的")] boy=1 , [Attributes.Remark("女的")] girl =2 } /// <summary> /// 提供擴展方法 /// </summary> public static class EnumExtension { public static string GetRemark(this Enum model) { if (model is ESex) { Type type = typeof(ESex); FieldInfo fi = type.GetField(model.ToString()); object[] attributes = fi.GetCustomAttributes(true); foreach (var attr in attributes) { if (attr is RemarkAttribute) { RemarkAttribute remark = (RemarkAttribute)attr; return remark.GetRemark(); } } } return string.Empty; } } class Program { public static void Main(string[] args) { Console.WriteLine(ESex.boy.GetRemark()); } }