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()); } }