目录
一、元数据和反射
二、Type类
三、获取Type类对象
1. 使用GetType方法获取Type对象
2.使用typeof运算符获取Type对象
四、特性
1. 什么是特性
2.应用特性
3.预定义特性
1. Obsolete特性
2. Conditional特性
3.调用者信息特性
4.DebuggerStepThrough特性
5.其他预定义特性
6.多个特性
7.将特性应用到其他类型的目标
8.全局特性
4.自定义特性
1.声明自定义特性
2.使用特性的构造函数
3.指定构造函数
4.使用构造函数
5.限制特性的使用
6.自定义特性的最佳实现准则
5.访问特性
BCL声明了一个叫做Type的抽象类,被设计用来包含类型的特性,使用这个类的对象能让我们获取程序使用的类型的信息。
因为所有类派生自object,所以任何类型对象可以调用GetType()方法获取它的Type对象。
格式:
代码:
class BaseClass
{
public int BaseField = 0;
}
class DerivedClass : BaseClass
{
public int DerivedField = 0;
}
internal class Program
{
static void Main(string[] args)
{
var bc = new BaseClass();
var dc = new DerivedClass();
BaseClass[] bca = new BaseClass[] { bc, dc };
foreach (var a in bca)
{
Type t = a.GetType();//获取类型
Console.WriteLine("Type对象:{0}",t.Name);
FieldInfo[] fieldInfos = t.GetFields();//获取类型中所有字段信息
foreach (FieldInfo fi in fieldInfos)
Console.WriteLine(" Field : {0}",fi.Name);//获取字段名
Console.WriteLine();
}
}
}
结果:
图解:
格式:
代码:
class BaseClass
{
private int privateBaseField;//私有字段
public int BaseField;
}
class DerivedClass : BaseClass
{
private int privateDerivedField;//私有字段
public int DerivedField;
}
internal class Program
{
static void Main(string[] args)
{
Type t = typeof(DerivedClass);//获取类型
Console.WriteLine("类型对象:{0}",t.Name);
FieldInfo[] fieldInfos = t.GetFields();//获取类型对象所有非私有字段
foreach (FieldInfo f in fieldInfos)
Console.WriteLine(" 字段:{0}",f.Name);
}
}
结果:
特性是一种允许我们向程序的程序集增加元数据的语言结构。它是用于保存程序结构信息的某种特殊类型的类。
特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集。
下面的代码演示了两个类的开始部分。最初的几行代码演示了把一个叫做Serializable的特性应用到MyClass。注意,Serializable没有参数列表。第二个类的声明有一个叫做MyAttribute的特性,它有一个带有两个string参数的参数列表。
使用Obsolete可以将程序结构标为过时的,但仍可继续使用。
使用Obsolete的重载特性,将程序结构标记为错误的,不能再使用。
Conditional允许我们包括或排斥特定方法的所有调用(搭配预处理指令编译符号使用)。
控制debug时不进入某些方法。可作用在类、结构、构造函数、方法或访问器。
我们可以为单个结构应用多个特性。
除了类,我们还可以将特性应用到诸如字段和属性等其他程序结构。例如:
我们还可以显式地标注特性,从而将它应用到特殊的目标结构。要使用显式目标,在特性片段的开始处放置目标类型,后面跟冒号。例如,如下的代码用特性装饰方法,并且还把特性应用到返回值上。
特性覆盖的目标:
我们还可以通过使用assembly和module目标名称来使用显式目标说明符把特性设置在程序集或模块级别。一些有关程序集级别的特性的要点如下:
特性只是某个特殊类型的类。
列在特性应用中的参数就是传给特性构造函数的参数。
特性也可以使用位置参数和命名参数,应用特性是一条声明语句,它不会决定什么时候构造特性类的对象。 (构造函数需要的任何位置参数都必须放在命名参数之前)
可以使用预定义类AttributeUsage特性,限制某个特性使用在某个目标类型上:
AttributeUsage特性重要的三个公共属性:
我们可以按位或来组合使用类型,但只能接受AttributeTarget枚举成员,下例被装饰的特性只能用在方法和构造函数上:
AttributeTarget枚举成员:
我们可以使用反射,获取特性类型信息。
(注:内容学习总结自《C#图解教程》)