特性,是一个类,声明的时候默认以Attribute 结尾,同时继承自Attribute抽象类
应用特性 ,以 [MyAttribute] 标记在类,或者类的内部成员上;(标记特性时,如果是以Attribute结尾则可以省略掉)
特性和注释的区别
注释在类编译后是不存在的,而特性由于他的本质是一个类,所以在编译之后是存在的通过反射就可以拿到特性里边的属性,方法;
通常特性可以标注在类的内部的任何成员上,
标记特性时,就是在调用特性类的构造函数
默认是不可以重复标记属性的
AttributeUsage:也是一个特性,是用来约束特性的特性
AttributeTargets 指定当前特性只能标记在某个地方
AllowMultiple 是否可以重复标记
Inherited 特性是否可以被继承 默认是
//表示只能标记到属性上,可以多次标记,可以被继承 [AttributeUsage(AttributeTargets.Property,AllowMultiple =true,Inherited =true)] public class RequiredAttribute : AbstractAttribute { } |
如何使用特性,因为特性本身也是一个类所以调用它要使用反射,在使用反射调用特性的时候可以把标记在任何地方的特性都获取到;
1.//新建一个枚举类 public enum Myenum { n=1, f=2, c=3 } 2. /// <summary> /// 新建一个Attribute标记类用来标记Enum, /// </summary> [AttributeUsage( AttributeTargets.All,AllowMultiple =true, Inherited =true)]//最好给特性设定能标记的范围 public class MyEnumAttribute:Attribute { /// <summary> /// 前边有提到过调用特性就是调用他的构造函数 /// </summary> public string Description { get; set; } public MyEnumAttribute(string _Description) { this.Description= _Description; } public string GetRemark() { return this.Description; } } 3.//实例化一个枚举 Myenum myenum = new Myenum(); //获取枚举中的某一个字段 var type = myenum.GetType().GetField("n"); //获取字段的标记 var atts = type.GetCustomAttribute<MyEnumAttribute>(); //调用特性中的放法 var rmk = atts.GetRemark(); //获取赋值给特性的值 Console.WriteLine(rmk);
//两种不同的调用方法 ,表格内为封装调用方式 |
除此之外 特性还可以应用于字段验证;
这里要有一个封装的思想,首先判断每个字段是否合法,就需要考虑有非常多种类的字段(有int,有string,有doubule等等)
类1 //只能标记到字段上 [AttributeUsage( AttributeTargets.Property,AllowMultiple=true, Inherited =true)] public abstract class CommonAttribute:Attribute { /// <summary> /// 父类公共验证的方法,需要传递要验证的参数 /// </summary> /// <param name="value"></param> /// <returns></returns> public abstract ResultMessage validation(object value);
} 类2 public class ProptyLingthAttribute : CommonAttribute { public int Min { get; set; } public int Max { get; set; } public ProptyLingthAttribute(int min, int max) { Min = min; Max = max; } public override ResultMessage validation(object value) { var valuestring=value.ToString(); if(!string.IsNullOrEmpty(valuestring)) { if (valuestring.Length <= Min || valuestring.Length >= Max) { return new ResultMessage() { Success = 2, Message = "字符长度不正确" }; } } return new ResultMessage() { Success = 1, Message = "字符不能为空" }; } } 类3 /// <summary> /// 结果返回包装 /// </summary> public class ResultMessage { public string? Message { get; set; } public int Success { get; set; } } 类4 /// <summary> /// 利用反射调用特性里的方法实现判断 /// </summary> public static class ValidateMethod { public static ResultMessage ValidateMeaage<T>(this T t)where T : class { Type type= typeof(T); PropertyInfo[] propertieyinfors= type.GetProperties(); foreach (var propertieyinfor in propertieyinfors) { var value = propertieyinfor.GetValue(t,null); var customs= propertieyinfor.GetCustomAttributes<CommonAttribute>(); foreach (var custom in customs) { return custom.validation(value); } } return new ResultMessage() { Success = 1, Message = "错误" }; } } 调用 var ceshi= ValidateMethod.ValidateMeaage(new Class1() { Name = "wulikao" }); |