该部分对应学习代码的下载地址
1.什么是特性?
特性其实就是一个类,直接或间接继承自Attribute
约定俗成以Attribute结尾,在标记的时候以[]包裹
通过反编译后,在中间语言IL中我们发现标记特性的元素内部都生成了一个.custom,但是我们调用不了
//[Obsolete("该类已过时")]
[Obsolete("该类已过时,请使用***代替",true)]
[Serializable]
public class TestClass
{
}
[Obsolete]和[Serializable]这两个特性是.Net内部定义的特性,我们无法修改
2.特性的声明和使用
//AttributeUsage对自定义特性进行约束,设置该特性标记的元素位置,如方法、属性、字段、全部等,建议明确特性所标记的元素
//[AttributeUsage(AttributeTargets.Method,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Class,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
//[AttributeUsage(AttributeTargets.Constructor,AllowMultiple = true)]
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)]
public class RulesAttribute : Attribute
{
public RulesAttribute()
{
Console.WriteLine($"{this.GetType().Name}特性类的无参构造函数");
}
public RulesAttribute(int iPar)
{
Console.WriteLine($"{this.GetType().Name}特性类的单参构造函数,参数类型:{iPar.GetType()},参数:{iPar}");
}
public RulesAttribute(string sPar)
{
Console.WriteLine($"{this.GetType().Name}特性类的单参构造函数,参数类型:{sPar.GetType()},参数:{sPar}");
}
public RulesAttribute(int iPar,string sPar)
{
Console.WriteLine($"{this.GetType().Name}特性类的双参构造函数,参数类型:{iPar.GetType()}、{sPar.GetType()},参数:{iPar}、{sPar}");
}
public string Remark { get; set; }
public string Description;
public void Show()
{
Console.WriteLine($"通过反射特性调用{this.GetType().Name}的Show方法");
}
}
[AttributeUsage(AttributeTargets.All,AllowMultiple = true)]
public class RulesChildAttribute : RulesAttribute
{
public RulesChildAttribute() : base(64,"渡边")
{
Console.WriteLine($"{this.GetType().Name}的父类没有空参构造函数时,子类可以:base(参数)来初始化父类的构造函数");
}
}
public class InvokeCenter
{
public static void ManagerStudent<T>(T t) where T : Student
{
Console.WriteLine($"学生姓名:{t.Name},学生编号:{t.Id}");
Console.WriteLine($"{t.Answer("渡边")}回答了问题");
Type type = typeof(T);
//判断该类型是否被特性RulesAttribute标记,这样可以节省性能,true表示父类被标记也可以算被标记
if (type.IsDefined(typeof(RulesAttribute), true))
{
object[] typeAttributes = type.GetCustomAttributes(typeof(RulesAttribute), true);
foreach(RulesAttribute attribute in typeAttributes)
{
attribute.Show();
}
Console.WriteLine();
foreach(FieldInfo field in type.GetFields())
{
if (field.IsDefined(typeof(RulesAttribute)))
{
object[] fieldAttributes = field.GetCustomAttributes(typeof(RulesAttribute), true);
foreach(RulesAttribute attribute in fieldAttributes)
{
attribute.Show();
}
}
}
Console.WriteLine();
foreach(PropertyInfo prop in type.GetProperties())
{
if (prop.IsDefined(typeof(RulesAttribute)))
{
object[] propAttributes = prop.GetCustomAttributes(typeof(RulesAttribute), true);
foreach(RulesAttribute attribute in propAttributes)
{
attribute.Show();
}
}
}
Console.WriteLine();
foreach(MethodInfo method in type.GetMethods())
{
if (method.IsDefined(typeof(RulesAttribute)))
{
object[] methodAttributes = method.GetCustomAttributes(typeof(RulesAttribute), true);
foreach(RulesAttribute attribute in methodAttributes)
{
attribute.Show();
}
}
}
}
}
}
3.特性应用一
标记的特性,需要用到反射
[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
public class RemarkAttribute : Attribute
{
public string _Remark { get; private set; }
public RemarkAttribute(string remark)
{
this._Remark = remark;
}
}
public static class RemarkAttributeExtend
{
public static string GetRemark(this Enum @enum)
{
Type type = @enum.GetType();
FieldInfo field = type.GetField(@enum.ToString());
if (field.IsDefined(typeof(RemarkAttribute)))
{
RemarkAttribute attribute = (RemarkAttribute)field.GetCustomAttribute(typeof(RemarkAttribute));
return attribute._Remark;
}
return @enum.ToString();
}
}
4.特性应用二
[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
public class QQAttribute : Attribute
{
public int _Min { get; set; }
public int _Max { get; set; }
public QQAttribute(int min,int max)
{
this._Min = min;
this._Max = max;
}
public bool Validate(object oValue)
{
return oValue != null && oValue.ToString().Length >= _Min && oValue.ToString().Length <= _Max;
}
}
public static class QQAttributeExtend
{
public static bool Validate(this StudentVIP student)
{
Type type = typeof(StudentVIP);
foreach(FieldInfo field in type.GetFields())
{
if (field.IsDefined(typeof(QQAttribute)))
{
QQAttribute attribute = (QQAttribute)field.GetCustomAttribute(typeof(QQAttribute));
return attribute.Validate(student.QQ);
}
}
return false;
}
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
public class SalaryAttribute : Attribute
{
public long _Salary { get; set; }
public SalaryAttribute(long salary)
{
this._Salary = salary;
}
public bool Validate(object oValue)
{
return oValue != null && long.TryParse(oValue.ToString(), out long lValue) && lValue >= _Salary;
}
}
public static class SalaryAttributeExtend
{
public static bool Validate(this StudentVIP student)
{
Type type = typeof(StudentVIP);
foreach(PropertyInfo prop in type.GetProperties())
{
if (prop.IsDefined(typeof(SalaryAttribute)))
{
SalaryAttribute attribute = (SalaryAttribute)prop.GetCustomAttribute(typeof(SalaryAttribute));
return attribute.Validate(student.Salary);
}
}
return false;
}
}
5.特性+泛型应用
public abstract class AbstractAttribute : Attribute
{
public abstract bool Validate(object oValue);
}
[AttributeUsage(AttributeTargets.Field,AllowMultiple = true)]
public class QQGenericAttribute : AbstractAttribute
{
public int _Min { get; set; }
public int _Max { get; set; }
public QQGenericAttribute(int min,int max)
{
this._Min = min;
this._Max = max;
}
public override bool Validate(object oValue)
{
return oValue != null && oValue.ToString().Length >= _Min && oValue.ToString().Length <= _Max;
}
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple = true)]
public class SalaryGenericAttribute : AbstractAttribute
{
public long _Salary { get; set; }
public SalaryGenericAttribute(long salary)
{
this._Salary = salary;
}
public override bool Validate(object oValue)
{
return oValue != null && long.TryParse(oValue.ToString(), out long lValue) && lValue >= _Salary;
}
}
public class GenericValidateAttributeExtend
{
public static bool FieldValidate<T>(T t)
{
Type type = typeof(T);
foreach(FieldInfo field in type.GetFields())
{
object oValue = field.GetValue(t);
if (field.IsDefined(typeof(AbstractAttribute)))
{
AbstractAttribute attribute = (AbstractAttribute)field.GetCustomAttribute(typeof(AbstractAttribute));
return attribute.Validate(oValue);
}
}
return false;
}
public static bool PropertyValidate<T>(T t)
{
Type type = typeof(T);
foreach(PropertyInfo prop in type.GetProperties())
{
object oValue = prop.GetValue(t);
if (prop.IsDefined(typeof(AbstractAttribute)))
{
AbstractAttribute attribute = (AbstractAttribute)prop.GetCustomAttribute(typeof(AbstractAttribute));
return attribute.Validate(oValue);
}
}
return false;
}
}
Model
[Rules(123,"渡边")]
public class Student
{
[Rules(123,"渡边")]
public Student()
{
Console.WriteLine($"{this.GetType().Name}的无参构造函数");
}
[Rules(123)]
public int Id { get; set; }
[Rules(123,"渡边")]
public string Name { get; set; }
public Achievement achievement;
[Rules(123,"渡边",Description = "正在学习",Remark = ".Net班")]
public void Study()
{
Console.WriteLine($"{this.Name}正在学习");
}
[Rules(123,"渡边",Description = "回答问题",Remark = ".Net班")]
public string Answer(string name)
{
return $"{name}回答了问题";
}
}
public class StudentVIP : Student
{
public string VipGroup { get; set; }
[QQ(5,10)]
[QQGeneric(4,8)]
public long QQ;
public void HomeWork()
{
Console.WriteLine($"调用{this.GetType().Name}的HomeWork方法");
}
[Salary(10000)]
[SalaryGeneric(20000)]
public long Salary { get; set; }
}
public enum Achievement
{
[Remark("优")]
Excellent = 0,
[Remark("良")]
Good = 1,
[Remark("中")]
Qulified = 2,
[Remark("差")]
Bad = 3
}