通过is运算符,能够判断对象类型是否为特定类型,如果两种类型是相同类型,或者两者之间存在引用,装箱拆箱转换,则表明两种类型是兼容的。
class PRogram { static void Main(string[] args) { A a = new A(); B b = new B(); if (a is A) { Console.WriteLine("a is an A"); //这个打印,因为a 是 A 类型的对象 } if (b is A) { //这个打印,因为b是B类型的对象,而B类型派生于A类型,由于b对象可以转换为A类型,因此b对象与A类型是兼容的,但是反过来就不成立,例如下面不打印 Console.WriteLine("b is an A because it is derived from"); } if (a is B) { //这个不打印 Console.WriteLine("This won't display , because a not derived from B"); } if (a is object) { //这个打印 Console.WriteLine("a is an object"); } Console.ReadKey(); } } class A { } class B : A { }
在运行期间执行类型转换,并且能够使得类型转换失败不抛异常,而返回一个null值,其实as也可以看作一个is运算符的简化备选方式(看例子)。
class Program { static void Main(string[] args) { A a = new A(); B b = new B(); if (a is B) { b = (B)a; //由于a变量不是B类型,因此这里将a变量转换为B类型是无效的。 } else { b = null; } if (b ==null) { //这个打印 Console.WriteLine("The cast in b=(B)a is not allowed"); } //上面使用as运算符,能够把两部合二为一。 b = a as B; //as类型先检查强制类型转换的有效性,如果有效,则执行强类型转换过程。这些都在这一句完成。 if (b == null) { //这个打印 Console.WriteLine("The cast in b=(B)a is not allowed"); } Console.ReadKey(); } } class A { } class B : A { }
as ,is 能够测试两种类型的兼容性。但大多数情况下,还需要获得某个类型的具体信息。这就用到了typeof,它可以返回与具体类型相关的System.Type对象,通过System.Type对象可以去顶此类型的特征。一旦获得给定类型的Type对象,就可以通过使用该对象定义的各种属性,字段,方法来获取类型的具体信息。Type类包含了很多成员,在接下来的反射中再详细讨论。下面简单的演示Type对象,调用它的三个属性。
static void Main(string[] args) { Type t=typeof(StringBuilder); Console.WriteLine(t.FullName); //FullName属性返回类型的全称 if (t.IsClass) { Console.WriteLine("is a class"); //打印 } if (t.IsSealed) //是否为密封类 { Console.WriteLine("is Sealed"); //打印 } Console.ReadKey(); }
MemberInfo类中的只读属性 | |
属性 | 描述 |
TypeDeclaringType | 获取声明该成员的类或接口的类型 |
MemberTypesMemberType | 获取成员的类型,这个值用于指示该成员是字段、方法、属性、事件、或构造函数 |
IntMetadataToken | 获取与特定元数据相关的值 |
ModuleModule | 获取一个代表反射类型所在模块(可执行文件)的Module对象 |
StringName | 成员的名称 |
TypeReflectedType | 反射的对象类型 |
请注意
当然除了MemberInfo类定义的方法和属性外,Type类自己也添加了许多属性和方法:如下表(只列出一些常用的,太多了,自己可以转定义Type类看下)
Type类定义的方法 | |
方法 | 功能 |
ConstructorInfo[] GetConstructors() | 获取指定类型的构造函数列表 |
EventInfo[] GetEvents(); | 获取指定类型的时间列 |
FieldInfo[] GetFields(); | 获取指定类型的字段列 |
Type[] GetGenericArguments(); | 获取与已构造的泛型类型绑定的类型参数列表,如果指定类型的泛型类型定义,则获得类型形参。对于正早构造的类型,该列表就可能同时包含类型实参和类型形参 |
MemberInfo[] GetMembers(); | 获取指定类型的成员列表 |
MethodInfo[] GetMethods(); | 获取指定类型的方法列表 |
PropertyInfo[] GetProperties(); | 获取指定类型的属性列表 |
下面列出Type类定义的常用的只读属性
Type类定义的属性 | |
属性 | 功能 |
Assembly Assembly | 获取指定类型的程序集 |
TypeAttributes Attributes | 获取制定类型的特性 |
Type BaseType | 获取指定类型的直接基类型 |
String FullName | 获取指定类型的全名 |
bool IsAbstract | 如果指定类型是抽象类型,返回true |
bool IsClass | 如果指定类型是类,返回true |
string Namespace | 获取指定类型的命名空间 |
上面的列术都是为了,这里的使用。
通过使用Type类定义的方法和属性,我们能够在运行时获得类型的各种具体信息。这是一个非常强大的功能。我们一旦得到类型信息,就可以调用其构造函数,方法,和属性。可见,反射是允许使用编译时不可用的代码的。
由于Reflection API非常多,这里不可能完整的介绍他们(这里如果完整的介绍,据说要一本书,厚书)。但是,Reflection API是按照一定逻辑设计的。因此,只要知道部分接口的使用方法,就可以举一反三的使用剩余的接口。
这里我列出四种关键的反射技术:
一旦有了Type对象就可以使用GetMethodInfo()方法获取此类型支持的方法列表。该方法返回一个MethodInfo 对象数组,MethodInfo对象描述了主调类型所支持的方法,他位于System.Reflection命名空间中
MethodInfo类派生于Method
新闻热点
疑难解答