一、什么是特性?
-
特性本质是一个class(类),声明的时候默认以Attribute结尾,直接或者间接继承Attribute抽象类
-
应用特性,是把这个特性以[ ]包裹标记在类或者类的成员上
-
Attribute是一种可由用户自有定义的修饰符(Modifier),可以用来修饰各种需要被修饰的目标。我们可以对类、以及C#程序集中的成员进行进一步的描述
代码示列:
[Serializable]
public class SampleClass
{
// Objects of this type can be serialized.
}
二、特性与注释的区别
-
注释只是一段描述文字,这段描述是给人看的,在编译器编译之后是不存在
-
Attribute是程序代码的一部分,它不但不会被编译器丢弃,而且还会被编译器编译进程序集
(Assembly)的元数据(Metadata)里。在程序运行的时候,随时可以从元数据(元数据:.NET中元数据是指程序集中的命名空间、类、方法、属性等信息,这些信息是可以通过Reflection读取出来的。)中提取提取出这些附加信息,并以之决策程序的运行。
三、如何自定义特性
-
标记的特性,如果是以Attribute结果,Attribute可以省略掉
-
可以标记的类内部的任何成员上
-
特性在标记的时候,其实就是去调用构造函数
-
在标记的时候也可以对公开的属性或者字段赋值
-
特性标记默认是不能重复标记的
-
AttributeUsage:也是一个特性,是用来修饰特性的特性–约束特性的特性
-
AttributeTargets指定当前特性只能标记在某个地方;建议大家在自己定义特性的时候,最好能够明确指定AttributeTargets–明确告诉别人,我这个特性是专们用来标记在哪里的.
-
AllowMultiple:是否可以重复标记.
-
Inherited:是否可以继承特性.
代码示列:
//完整写法
[CustomAttribute("Jun")]
[CustomAttribute("Sun")]
public static void Test()
{
Console.WriteLine("Hello Jun Sun");
}
//省去Attribute写法
[Custom("Jun")]
[Custom("Sun")]
public static void Test2()
{
Console.WriteLine("Hello Jun Sun");
}
//执行的顺序
[Custom("Sub")]
[Custom("Jun")]
public static void Test3()
{
Console.WriteLine("Sun Jun");
}
//单括号叠加
[Custom("Sun"),Custom("Jun")]
public static void Func()
{
Console.WriteLine("Sun Jun");
}
四、如何调用特性内部的成员
-
进过反编译之后,在标记有特性的类的内部,生成了cutom的成员,但是我们不能直接调用.
-
在使用反射获取特性的时候,可以把标记在任何地方的特性都可以获取到
-
既然标记的特性可以通过反射来获取到实例,就可以加以应用
代码实例:
public class InvokeAttributeManager
{
/// <summary>
/// 通过反射来调用特性---确实是可以调用到特性的实例的
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
public static void Show(Student student)
{
//Type type = typeof(Student);
Type type = student.GetType();
//1.先判断是否有特性
if (type.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in type.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
//获取当前Type下所有的属性上标记的特性
foreach (PropertyInfo prop in type.GetProperties())
{
if (prop.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in prop.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
//获取当前Type下所有的字段上标记的特性
foreach (FieldInfo field in type.GetFields())
{
if (field.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in field.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
//获取当前Type下所有的方法上标记的特性
foreach (MethodInfo method in type.GetMethods())
{
foreach (ParameterInfo para in method.GetParameters())
{
if (para.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in para.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
if (method.IsDefined(typeof(CustomAttribute), true))
{
//2.获取--先判断再获取--为了提高性能
foreach (CustomAttribute attribute in method.GetCustomAttributes(true))
{
Console.WriteLine($"attribute._Name:{attribute._Name}");
Console.WriteLine($"attribute._Age:{attribute._Age}");
attribute.Do();
}
}
}
}
}
staic void Main(int[] args)
{
People people = new People()
{
Id = 1,
Name = "明天我是否在"
};
people.custom//调用不到
InvokeAttributeManager.Show(people);
}
五、特性获取额外信息
- 特性获取描述信息—获取额外信息
- 通过反射、特性、扩展方法,可以封装一个获取额外新的的公共方法
代码示列:
[AttributeUsage(AttributeTargets.Field)]
public class RemarkAttribute : Attribute
{
private string _Description;
public RemarkAttribute(string decription)
{
this._Description = decription;
}
public string GetRemark()
{
return this._Description;
}
}
public enum UserStateEnum
{
[Remark("正常状态")]
Normal = 1,
[Remark("已冻结")]
Frozen = 2,
[Remark("已删除")]
Deleted = 3,
[Remark("其他")]
Other = 4
}
public static class RemarkAttributeExtension
{
/// <summary>
/// 扩展方法
/// </summary>
/// <param name="enum"></param>
/// <returns></returns>
public static string GetRemark(this Enum @enum)
{
Type type = @enum.GetType();
string fieldName = @enum.ToString();
FieldInfo field = type.GetField(fieldName);
if (field.IsDefined(typeof(RemarkAttribute), true))
{
//RemarkAttribute attribute = (RemarkAttribute)field.GetCustomAttribute(typeof(UserStateEnum), true);
RemarkAttribute attribute = field.GetCustomAttribute<RemarkAttribute>();
string description = attribute.GetRemark();
return description;
}
return @enum.ToString();
}
}
static void Main(string[] args)
{
UserStateEnum normal = UserStateEnum.Normal;
UserStateEnum frozen = UserStateEnum.Frozen;
UserStateEnum deleted = UserStateEnum.Deleted;
UserStateEnum other = UserStateEnum.Other;
UserStateEnum other1 = UserStateEnum.Other1;
string strnormalRemark = RemarkAttributeExtension.GetRemark(normal);
string strfrozenRemark = RemarkAttributeExtension.GetRemark(frozen);
string strdeletedRemark = RemarkAttributeExtension.GetRemark(deleted);
string strotherRemark = RemarkAttributeExtension.GetRemark(other);
string strother1Remark = RemarkAttributeExtension.GetRemark(other1);
}
本人学习分享,如有错误,欢迎指正,请勿谩骂(* ̄︶ ̄)