特性,是用来给代码添加额外信息的一种手段,我们通常是将特性标记到方法,类或者属性上,在使用的这些结构的时候,通过反射(reflection)这一非常高级的技术,获取它们通过特性标记的信息,从而进行某些特殊的处理。
和java的注解差不多
系统也给我们提供了一些特性,比如Serializable 标记一个可序列化的类,用法在成员上写个中括号。
它其实是省略了(),如果使用特性的其它的构造方法,显示声明即可:
[Serializable]
[Serializable("test")]
class Sunshine{...}
自定义特性
自定义特性,很简单,让一个类继承Attribute类即可,另外,自定义的特性,名称后缀约定是Attribute结尾,使用的时候这个后缀可以省略
class MyAttribute : Attribute
{
private string name;
private int age;
public MyAttribute(string name,int age)
{
this.name = name;
this.age = age;
}
public void GetName()
{
Console.WriteLine($"my name is {name}");
}
public void GetAge()
{
Console.WriteLine($"my age is {age}");
}
}
[My("张三",13)]
class Person
{
public Person(string name,int age)
{
this.Name = name;
this.Age = age;
}
public string Name { get;private set; }
public int Age { get;private set; }
}
通过反射获取特性信息
static void Main(string[] args)
{
//获取Person类的元数据
Type type = typeof(Person);
//获取类上面的全部特性
IEnumerable<Attribute> attributes = type.GetCustomAttributes();
foreach(var a in attributes)
{
//判断遍历的a是不是MyAttribute
if (a is MyAttribute)
{
//转换类型
MyAttribute my = a as MyAttribute;
//反射创建对象
Person person = (Person)Activator.CreateInstance(type, my.GetName(), my.GetAge());
Console.WriteLine("反射出来的对象姓名:"+ person.Name);
Console.WriteLine("反射出来的对象年龄:" + person.Age);
}
}
}
指定特性用法
AttributeUsageAttribute特性放在自定义的特性上面,指定特性的用法。用法查看编写自定义特性
特性参数
许多特性都有参数,而这些参数可以是普通参数、命名参数。任何普通参数都必须按特定顺序指定并且不能省略,而命名参数是可选的且可以按任意顺序指定。首先指定普通参数。
例子:
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
这是AttributeUsage特性,构造器普通参数就一个