Attribute定义:特性其实是一个类,是直接/间接继承自Attribute,约定俗成是以Attribut结尾,在标记的时候以[]包裹,尾部的Attribut可以省略掉;
Attribute作用:可以增加额外信息,增加额外功能,但让特性生效需要使用反射;
Attribute的使用场景:MVC,WCF,ORM等;
多说不宜,直接上代码:
定义Attribute:
/// <summary>
/// 自定义特性
/// AllowMultiple =true:标记在特性上的特性,其实是对特性的一种约束;
/// Inherited =true:约束当前特性是否可以继承
/// AttributeTargets.All:当前特性可以标记在所有的元素上
/// AttributeUsage:在定义特性的时候,对特性的一种约束
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
public class CustomAttribute : Attribute
{
public CustomAttribute()
{
}
public CustomAttribute(int id)
{
}
public CustomAttribute(string name)
{
}
public CustomAttribute(int id,string name)
{
this.Id = id;
this.Name = name;
}
public string Description;
public int Id { get; set; }
public string Name { get; set; }
public int Do()
{
return 1;
}
}
}
利用反射获取Attribute信息并执行方法:
public static void ReflectionArrtibute<T>(T t) where T : Class
{
Type type = t.GetType();//通过参数来获取Type类型
if (type.IsDefined(typeof(CustomAttribute),true)) //反射调用特性,记得一定要先判断,然后再获取
{
foreach (CustomAttribute attribute in type.GetCustomAttributes()) //把所有标记的特性都实例化了
{
Console.WriteLine($"attribute.Id={attribute.Id}");
Console.WriteLine($"attribute.Name={attribute.Name}");
attribute.Do();
}
///循环获取所有的属性上标记的特性,调用特性中的元素
foreach (PropertyInfo prop in type.GetProperties())
{
if (prop.IsDefined(typeof(CustomAttribute), true))
{
foreach (CustomAttribute attribute in prop.GetCustomAttributes()) //把所有标记的特性都实例化了
{
Console.WriteLine($"attribute.Id={attribute.Id}");
Console.WriteLine($"attribute.Name={attribute.Name}");
attribute.Do();
}
}
}
///循环获取所有的字段上标记的特性,调用特性中的元素
foreach (FieldInfo field in type.GetFields())
{
if (field.IsDefined(typeof(CustomAttribute), true))
{
foreach (CustomAttribute attribute in field.GetCustomAttributes()) //把所有标记的特性都实例化了
{
Console.WriteLine($"attribute.Id={attribute.Id}");
Console.WriteLine($"attribute.Name={attribute.Name}");
attribute.Do();
}
}
}
///循环获取所有方法上标记的特性,调用特性中的元素
foreach (MethodInfo method in type.GetMethods())
{
if (method.IsDefined(typeof(CustomAttribute), true))
{
foreach (CustomAttribute attribute in method.GetCustomAttributes()) //把所有标记的特性都实例化了
{
Console.WriteLine($"attribute.Id={attribute.Id}");
Console.WriteLine($"attribute.Name={attribute.Name}");
attribute.Do();
}
}
}
}
将枚举值的中文扩展信息添加到Attribute:
//新增ExplainAttribute
[AttributeUsage( AttributeTargets.All,AllowMultiple =true,Inherited =true)]
public class ExplainAttribute :Attribute
{
public string Explain { get; private set; }
public ExplainAttribute(string explain)
{
this.Explain = explain;
}
}
//创建枚举
public enum GameState
{
[ExplainAttribute("开始")]
Start,
[ExplainAttribute("暂停")]
Stop,
[ExplainAttribute("继续")]
GoOn
}
//获取Attribute信息
public static class ExplainExtension
{
public static string GetExplain(this Enum @enum)
{
Type type = @enum.GetType();
FieldInfo field = type.GetField(@enum.ToString());
if (field != null)
{
if (field.IsDefined(typeof(ExplainAttribute), true))
{
ExplainAttribute attribute = field.GetCustomAttribute<ExplainAttribute>();
return attribute.Explain;
}
}
return @enum.ToString();
}
}
使用Attribute验证输入信息:
//定义用于验证的Attribute
[AttributeUsage(AttributeTargets.Property)]
public class MobileNumAtrribute : AbstractValidateAttribute
{
public int Count { get; private set; }
public MobileNumAtrribute(int count)
{
if (count<=0)
{
throw new Exception("手机号长度不可能为负数");
}
Count = count;
}
public override bool Validate(object mobileNum)
{
return mobileNum != null && mobileNum.ToString().Length == Count;
}
}
//定义需要验证的类
public class Student
{
public string Description;
public string QQ { get; set; }
[MobileNumAtrribute(11)]
public long MobileNum { get; set; }
}
//验证
public static bool Validate<T>(T t)
{
Type type = t.GetType();
foreach (PropertyInfo prop in type.GetProperties())
{
/ 验证手机号长度
if (prop.IsDefined(typeof(MobileNumAtrribute), true))
{
object oValue = prop.GetValue(t);
MobileNumAtrribute atrribute = prop.GetCustomAttribute<MobileNumAtrribute>(true);
if (!atrribute.Validate(oValue))
{
return false;
}
}
return true;
}
网友评论