程序是用来处理数据的,文本和特性都是数据,而我们程序本身(类的定义和BLC中的类)这些也是数据。
有关程序及其类型的数据被称为元数据(metadata),它们保存在程序的程序集中。
程序在运行时,可以查看其它程序集或其本身的元数据。一个运行的程序查看本身的元数据或者其他程序集的元数据的行为叫做反射。
特性(attribute)是一种允许我们向程序的程序集增加元数据的语言结构。它是用于保存程序结构信息的某种特殊类型的类。
将应用了特性的程序结构叫做目标
设计用来获取和使用元数据的程序(对象浏览器)叫做特性的消费者
.NET预定了很多特性,我们也可以声明自定义特性
.NET预定义特性
[CallerLineNumber]:在哪一行被调用
[CallerMemberName]:调用者名称
自定义特性
自定义特性注意的几点:
特性类的后缀以Attribute结尾
需要继承System.Attribute
一般声明为sealed
一般情况下特性类用来表示目标特性的一些状态(定义一些字段或这属性,一般不定义方法)
MyTestAttribute.CS
[AttributeUsage(AttributeTargets.Class)]//表示该特性类可以运用到的程序结构有哪些
sealed class MyTestAttribute:System.Attribute
{
public string Description { get; set; }
public string VersionNum { get; set; }
public int Id { get; set; }
public MyTestAttribute(string desc)
{
this.Description = desc;
}
}
使用特性:
[MyTest("简单的特性类",Id=100)]//通过属性名字给属性赋值称为命名参数
class Program
{
[Obsolete("这个方法过时了,使用newMethod代替",true)]//表示方法被弃用
static void OldMethod()
{
}
static void NewMethod()
{
}
[Conditional("IsTest")]
static void Test1()
{
Console.WriteLine("Test1");
}
static void Test2()
{
Console.WriteLine("Test2");
}
//调用者信息特性
[DebuggerStepThroughAttribute]//跳过debug测试
static void PrintOut([CallerFilePath]string filename="",[CallerLineNumber]int linenum=0,[CallerMemberName]string mebername="")
{
Console.WriteLine(filename);
Console.WriteLine(linenum);
Console.WriteLine(mebername);
}
/// <summary>
/// 特性是一种允许我们向程序集增加元数据的程序结构,它是用于保存程序结构信息的某种特殊类型的类
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
Type type = typeof(Program);//获取Type对象
object []o= type.GetCustomAttributes(false);
Console.WriteLine((o[0] as MyTestAttribute).Id);
Console.WriteLine((o[0] as MyTestAttribute).Description);
Test1();
Test1();
Test2();
PrintOut();
Console.ReadKey();
}
}