1. 反射和特性
1.1 概念
- 有关程序及其类型的数据被称为元数据,他们保存在程序的程序集中
- 程序在运行时,可以查看其它程序或其本身的元数据,运行中的程序查看本身的元数据或者其它程序的元数据的行为叫做反射。
BCL声明了一个Type的抽象类,用来包含类型的特征。可以从Type对象中获取有关类型的几乎所有信息,
可以通过实例对象的GetType方法或者typeof运算符来获得Type对象,object类型包含一个叫Gettype的方法。
1.2. 自定义特性
要声明一个自定义特性,需要如下工作
- 声明一个派生自System.Atrribute的类
- 给它起一个以后缀"Attribute"结尾的名字
自定义特性的最佳实践:
- 特性类应该表示目标结构的某种状态
- 如果特性需要某些字段,可以通过包含具体位置参数的构造函数来收集数据
- 除属性之外,不要实现公有方法或其它函数成员
- 为了安全,把特性类什么为sealed。
- 在特性声明中使用Attributeusage来显示指定目标组
1.3 访问特性
可以使用Type对象的IsDefined方法来检测
第一个参数接受需要检查的type对象
第二个参数是bool类型,它知识是否搜索MyClass的继承树来查找这个特性
[My("test","1.0")]
internal class AttributeStudy
{
public static void Test()
{
AttributeStudy s=new AttributeStudy();
Type t=s.GetType();
bool isDefined=t.IsDefined(typeof(MyAttribute),false);
if (isDefined)
Console.WriteLine($" MyAttribute is applied to type {t.Name}");
}
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class MyAttribute:Attribute
{
public MyAttribute(string s,string v)
{
Description = s;
VersionNumber = v;
}
public string Description { get; set; }
public string VersionNumber { get; set; }
}
Type类的GetCustomeAttributes方法返回应用到结构上的特性的数组,实际返回的对象是object数组,因此我们必须将它强制转换为相应的特性类型。布尔参数指定是否搜索继承树来查找特性。调用GetCustomeAttribute方法后,每一个与目标关联的特性的实例就会被创建。
基于上面的例子:
public static void Test2()
{
Type t = typeof(AttributeStudy);
object[] attrs=t.GetCustomAttributes(false);
foreach(var attr in attrs)
{
var myAttr=attr as MyAttribute;
if(myAttr!=null)
{
Console.WriteLine($"Description : {myAttr.Description}");
Console.WriteLine($"Version no : {myAttr.VersionNumber}");
}
}
}
运行结果如下:
Description : test
Version no : 1.0
(未完待续,持续补充。。。)