1.元数据与反射
有关程序以及其类型的数据称作元数据(也有叫做描述数据的数据),它保存在程序的程序集中。一个程序在运行时查看自己程序的元数据或者其他程序的元数据的行为就叫做反射。
2.Type类
Type类包扩了我们程序使用的类型信息:
成员 | 成员类型 | 描述 |
Name | 属性 | 类型的名字 |
NameSpace | 属性 | 类型声明的命名空间 |
Assembly | 属性 | 返回声明类型的程序集。如果类型是泛型的,返回定义这个类型的程序集 |
GetFields | 方法 | 返回类型的字段列表 |
GetProperties | 方法 | 返回类型的属性列表 |
GetMethods | 方法 | 返回类型的方法列表 |
....... | ...... | ........ |
PropertyInfo类型,封装了类型的属性信息;
❑ConstructorInfo类型,封装了类型的构造函数信息;
❑MethodInfo类型,封装了类型的方法信息;
❑EventInfo类型,封装了类型的事件信息;
❑ParameterInfo类型,封装了方法和构造函数的参数信息
经常使用的两种方式获取Type对象:
Type t=typeof(希望被获取类型的对象)
Type tt=类型对象.GetType();
namespace 测试反射 { public class Program { static void Main(string[] args) { FatherClass fatherClass=new FatherClass(); DerivedClass derivedClass=new DerivedClass(); //PrintInfo(typeof(FatherClass)); //PrintInfo(typeof(DerivedClass)); PrintInfo(fatherClass.GetType()); PrintInfo(derivedClass.GetType()); Console.ReadKey(); } static void PrintInfo(Type t) { Console.WriteLine("Name:" + t.Name + " " + "NameSpace" + t.Namespace + " " + "Assmbly" + t.Assembly + " "); Console.WriteLine("字段信息:"); FieldInfo[] fieldInfos = t.GetFields(); foreach (var fieldInfo in fieldInfos) { Console.WriteLine(" "+fieldInfo.Name); } Console.WriteLine("属性信息:"); PropertyInfo[] propertyInfos = t.GetProperties(); foreach (var propertyInfo in propertyInfos) { Console.WriteLine(" " + propertyInfo.Name); } Console.WriteLine("方法信息:"); MethodInfo[] methodInfos = t.GetMethods(); foreach (var method in methodInfos) { Console.WriteLine(" " + method.Name); } Console.WriteLine("======================="); } } public class FatherClass { public int baseFiled = 0; public string BaseProperty { get; set; } public void BaseMethod() { Console.WriteLine("I am a Father Method"); } } public class DerivedClass:FatherClass { public int derivedFiled = 1; public string DerivedProperty { get; set; } public void DerivedMethod() { Console.WriteLine("I am a Derived Method"); } } }
输出的结果如图:
继承的一些信息也被打印了出来。
3.通过GetField()属性,反射枚举类型的字段。因为枚举获取的Field值得首项不是枚举中的业务字段,通过IsSpecialName进行区分
namespace 枚举类型的反射 { public class Program { static void Main(string[] args) { Type t = typeof(Day); FieldInfo[] infos = t.GetFields(); foreach (var field in infos) { if (!field.IsSpecialName) { Console.WriteLine("filedName" + field.Name + "FiledValue" + Convert.ToString(field.GetRawConstantValue())); } } Console.Read(); } } enum Day { Monday=1, Tuesday, Wednesday, Friday } }
执行结果:
4.MemberInfo
type中在vs中能点出来的属性和方法一般是Is...,Get....,Get....s。他们都继承于MemberInfo。MemberInfo是一个抽象类,它通过位标记(用[Flags]特性标记的枚举)来进行区分,是FiledInfo还是ProperityInfo等等。下面是在代码中F12看到的MemberType枚举。
// 摘要: // 标记每个已定义为 MemberInfo 的派生类的成员类型。 [Serializable] [ComVisible(true)] [Flags] public enum MemberTypes { // 摘要: // 指定该成员是一个构造函数,表示 System.Reflection.ConstructorInfo 成员。0x01 的十六进制值。 Constructor = 1, // // 摘要: // 指定该成员是一个事件,表示 System.Reflection.EventInfo 成员。0x02 的十六进制值。 Event = 2, // // 摘要: // 指定该成员是一个字段,表示 System.Reflection.FieldInfo 成员。0x04 的十六进制值。 Field = 4, // // 摘要: // 指定该成员是一个方法,表示 System.Reflection.MethodInfo 成员。0x08 的十六进制值。 Method = 8, // // 摘要: // 指定该成员是一个属性,表示 System.Reflection.PropertyInfo 成员。0x10 的十六进制值。 Property = 16, // // 摘要: // 指定该成员是一种类型,表示 System.Reflection.MemberTypes.TypeInfo 成员。0x20 的十六进制值。 TypeInfo = 32, // // 摘要: // 指定该成员是一个自定义成员类型。0x40 的十六进制值。 Custom = 64, // // 摘要: // 指定该成员是一个嵌套类型,可扩展 System.Reflection.MemberInfo。 NestedType = 128, // // 摘要: // 指定所有成员类型。 All = 191, }
好,初次认识反射,对于Type获取对象元数据信息有了一个基本了解。后面会继续讲解。