c#学习反射
http://www.cnblogs.com/wangshenhe/p/3256657.html
http://blog.csdn.net/educast/article/details/2894892
1、程序集包括exe和dll两种,反射(reflect)就是从程序集中获得元数据的方法。
2、命名空间和装配件的关系
命名空间只是说明一个类型是那个族的,比如有人是汉族、有人是回族;而装配件表明一个类型住在哪里,比如有人住在北京、有人住在上海
装配件是.Net应用程序执行的最小单位,编译出来的.dll、.exe都是装配件。
装配件和命名空间的关系不是一一对应,也不互相包含,一个装配件里面可以有多个命名空间,一个命名空间也可以在多个装配件中存在
装配件是一个类型居住的地方, 在一个程序中要使用一个类,就必须告诉编译器这个类住在哪儿,编译器才能找到它,也就是说必须引用该装配件。
那么如果在编写程序的时候,也许不确定这个类在哪里,仅仅只是知道它的名称,就不能使用了吗?答案是可以,这就是反射了,就是在程序运行的时候提供该类型的地址,而去 找到它。
3、反射用到的命名空间:
1)System.Reflection、
2)System.Type 通过这个类可以访问任何给定数据类型的信息,但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。
3)System.Reflection.Assembly 用于访问给定程序集的信息,或者把这个程序集加载到程序中
Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。
Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。
4、反射的用途:
(1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
(2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
1 private void button1_Click(object sender, EventArgs e) 2 { 3 NewClass mClass=new NewClass(); 4 Type t=mClass.GetType(); 5 //获取类的所有构造函数 6 ConstructorInfo[] ci=t.GetConstructors(); 7 foreach(ConstructorInfo c in ci) 8 { 9 //获取构造函数的所有参赛 10 ParameterInfo[] ps=c.GetParameters(); 11 foreach(ParameterInfo pi in ps) 12 { 13 MessageBox.Show(pi.ParameterType.ToString()+"" +pi.Name); 14 } 15 } 16 //查看类中的属性 17 PropertyInfo[] pis=t.GetProperties(); 18 foreach(PropertyInfo pi in pis) 19 { 20 MessageBox.Show(pi.Name); 21 } 22 23 //查看类中Public方法 24 MethodInfo[] mis =t.GetMethods(); 25 foreach(MethodInfo mi in mis) 26 { 27 MessageBox.Show(mi.ReturnType+" "+mi.Name); 28 } 29 30 //查看类中public字段 31 FieldInfo[] fis=t.GetFields(); 32 foreach(FieldInfo fi in fis) 33 { 34 MessageBox.Show(fi.Name); 35 } 36 37 //用反射生成对象 38 object obj=Activator.CreateInstance(t); 39 //取得字段ID 40 FieldInfo fiInfo=t.GetField("ID"); 41 //给字段赋值 42 fiInfo.SetValue(obj,"001"); 43 44 //取得show方法 45 MethodInfo miInfo=t.GetMethod("show"); 46 miInfo.Invoke(obj,null); 47 48 //通过程序集的名称反射 49 Assembly ass=Assembly.Load("ClassLibrary"); 50 Type t1=ass.GetType("ClassLibrary.NewClass"); 51 52 //通过DLL全名反射其中所有的类型 53 Assembly assmebly=Assembly.LoadFrom("**路径"); 54 Type[] aa=assmebly.GetTypes(); 55 56 }
5、Type类的属性:
Name 数据类型名 FullName 数据类型的完全限定名(包括命名空间名)
Namespace 定义数据类型的命名空间名 IsAbstract 指示该类型是否是抽象类型
IsArray 指示该类型是否是数组 IsClass 指示
1 private void button6_Click(object sender, EventArgs e) 2 { 3 //获取私有类型的值 4 Type t = typeof(RefClass); 5 RefClass rc = new RefClass(); 6 rc.test4 = 3; 7 PropertyInfo[] propertyInfos = t.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | 8 BindingFlags.Instance | BindingFlags.DeclaredOnly); 9 string s = ""; 10 foreach (PropertyInfo propertyInfo in propertyInfos) 11 { 12 //调用该方法时如果传入true则无法获取非公开的get方法 13 MethodInfo getInfo = propertyInfo.GetGetMethod(true); 14 string getStr = String.Format("Get字段名称:{0} 返回值类型:{1} 参数数量为:{2} MSIL代码长度为:{3} 局部变量数量为:{4};", 15 getInfo.Name, getInfo.ReturnType.ToString(),getInfo.GetParameters().Count(), 16 getInfo.GetMethodBody().GetILAsByteArray().Length,getInfo.GetMethodBody().LocalVariables.Count); 17 MethodInfo setInfo = propertyInfo.GetSetMethod(true); 18 string setStr = String.Format("Set字段名称:{0} 返回值类型:{1} 参数数量为:{2} MSIL代码长度为:{3} 局部变量数量为:{4};", 19 getInfo.Name, getInfo.ReturnType.ToString(), getInfo.GetParameters().Count(), 20 getInfo.GetMethodBody().GetILAsByteArray().Length, getInfo.GetMethodBody().LocalVariables.Count); 21 //调用了set方法将值改变,然后再通过调用get方法获取这个属性的值。 22 setInfo.Invoke(rc, new object[] { 123 }); 23 object obj = getInfo.Invoke(rc, null); 24 string invokeStr = String.Format("方法名:{0} 内部值:{1};", propertyInfo.Name, obj); 25 s += getStr+setStr+ invokeStr; 26 } 27 MessageBox.Show(s); 28 //Get字段名称:get_test1 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 29 //Set字段名称:get_test1 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 30 //方法名:test1 内部值:123; 31 32 //Get字段名称:get_test2 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 33 //Set字段名称:get_test2 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 34 //方法名:test2 内部值:123; 35 36 //Get字段名称:get_test4 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 37 //Set字段名称:get_test4 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 38 //方法名:test4 内部值:123; 39 }
该类型是否是类
IsEnum 指示该类型是否是枚举 IsInterface 指示该类型是否是接口
IsPublic 指示该类型是否是公有的 IsSealed 指示该类型是否是密封类
IsValueType 指示该类型是否是值类型
6、Type类的方法:
GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息
GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息
GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息
GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息
GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息
GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息
7.区分属性和方法
1 private void button3_Click(object sender, EventArgs e) 2 { 3 //区分属性和方法 4 Type t = typeof(RefClass); 5 Func<MemberTypes, String> getType = (x) => 6 { 7 switch (x) 8 { 9 case MemberTypes.Field: 10 { 11 return "字段"; 12 } 13 case MemberTypes.Method: 14 { 15 return "方法"; 16 } 17 case MemberTypes.Property: 18 { 19 return "属性"; 20 } 21 default: 22 { 23 return "未知"; 24 } 25 } 26 }; 27 MemberInfo[] minfos = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance | 28 BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static); 29 string s = ""; 30 foreach (MemberInfo me in minfos) 31 { 32 s += me.Name + ":类型为"+getType(me.MemberType); 33 } 34 MessageBox.Show(s); 35 //get_test1:类型为方法 set_test1:类型为方法 get_test2:类型为方法 set_test2:类型为方法 36 //get_test4:类型为方法 set_test4:类型为方法 Show:类型为方法 show2:类型为方法 37 //show3:类型为方法 .ctor:类型为未知 test1:类型为属性 test2:类型为属性 38 //test4:类型为属性 test3:类型为字段 <test1>k__BackingField:类型为字段 39 //<test2>k__BackingField:类型为字段 <test4>k__BackingField:类型为字段 40 41 }
8.获取属性、方法
1 private void button2_Click(object sender, EventArgs e) 2 { 3 Type t=typeof(RefClass); 4 //MemberInfo[] minfos=t.GetMembers(); 5 ////结果:get_test4;set_test4;Show;ToString;Equals;GetHashCode;GetType; 6 7 // 从中我们看到我们使用了GetMembers的重载版本,并且传入了枚举类型,分别是“包含非公开”、“包含实例成员”和“包含公开”。然后我们就可以获取到所有成员了。 8 //MemberInfo[] minfos = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 9 //get_test1;set_test1;get_test2;set_test2;get_test4;set_test4;Show;ToString; 10 //Equals;GetHashCode;GetType;Finalize;MemberwiseClone;.ctor;test1;test2; 11 //test4;test3;<test1>k__BackingField;<test2>k__BackingField;<test4>k__BackingField; 12 13 //到这里你可能会认为我们已经检索结束了,但是你有没有发现属性很多, 14 //而且还包含了大量的父类中的属性,假设我们只关注该类中的成员,并不关注父类中的成员该如何做呢? 15 16 //其实我们只需要加上一个枚举类型(BindingFlags.DeclaredOnly): 17 // MemberInfo[] minfos = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public|BindingFlags.DeclaredOnly); 18 //get_test1;set_test1;get_test2;set_test2;get_test4;set_test4;Show;.ctor;test1;test2;test4; 19 //test3;<test1>k__BackingField;<test2>k__BackingField;<test4>k__BackingField; 20 21 22 //获取静态类,只需加上BindingFlags.Static 23 MemberInfo[] minfos = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance | 24 BindingFlags.Public | BindingFlags.DeclaredOnly|BindingFlags.Static); 25 //get_test1;set_test1;get_test2;set_test2;get_test4;set_test4; 26 //Show;show2;show3;.ctor;test1;test2;test4;test3;<test1>k__BackingField; 27 //<test2>k__BackingField;<test4>k__BackingField; 28 29 30 string s=""; 31 foreach(MemberInfo me in minfos) 32 { 33 s+=me.Name+";"; 34 } 35 MessageBox.Show(s); 36 37 }
9.获取私有类型的值
1 private void button4_Click(object sender, EventArgs e) 2 { 3 //获取私有类型的值 4 Type t = typeof(RefClass); 5 RefClass rc = new RefClass(); 6 rc.test4 = 3; 7 FieldInfo[] fieldInfos = t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | 8 BindingFlags.Instance | BindingFlags.DeclaredOnly); 9 string s = ""; 10 foreach (FieldInfo fieldInfo in fieldInfos) 11 { 12 string m=String.Format("字段名称:{0} 字段类型:{1} rc中的值为:{2};",fieldInfo.Name,fieldInfo.FieldType.ToString(),fieldInfo.GetValue(rc)); 13 s += m; 14 } 15 MessageBox.Show(s); 16 //字段名称:test3 字段类型:System.Int32 rc中的值为:0; 17 //字段名称:<test1>k__BackingField 字段类型:System.Int32 rc中的值为:0; 18 //字段名称:<test2>k__BackingField 字段类型:System.Int32 rc中的值为:0; 19 //字段名称:<test4>k__BackingField 字段类型:System.Int32 rc中的值为:3; 20 }
10.修改私有类型的值
1 private void button5_Click(object sender, EventArgs e) 2 { 3 //获取私有类型的值 4 Type t = typeof(RefClass); 5 RefClass rc = new RefClass(); 6 rc.test4 = 3; 7 FieldInfo[] fieldInfos = t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | 8 BindingFlags.Instance | BindingFlags.DeclaredOnly); 9 string s = ""; 10 foreach (FieldInfo fieldInfo in fieldInfos) 11 { 12 fieldInfo.SetValue(rc, 100); 13 string m = String.Format("字段名称:{0} 字段类型:{1} rc中的值为:{2};", fieldInfo.Name, fieldInfo.FieldType.ToString(), fieldInfo.GetValue(rc)); 14 s += m; 15 } 16 MessageBox.Show(s); 17 //字段名称:test3 字段类型:System.Int32 rc中的值为:100; 18 //字段名称:<test1>k__BackingField 字段类型:System.Int32 rc中的值为:100; 19 //字段名称:<test2>k__BackingField 字段类型:System.Int32 rc中的值为:100; 20 //字段名称:<test4>k__BackingField 字段类型:System.Int32 rc中的值为:100; 21 }
11.通过set修改属性值
1 private void button6_Click(object sender, EventArgs e) 2 { 3 //获取私有类型的值 4 Type t = typeof(RefClass); 5 RefClass rc = new RefClass(); 6 rc.test4 = 3; 7 PropertyInfo[] propertyInfos = t.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | 8 BindingFlags.Instance | BindingFlags.DeclaredOnly); 9 string s = ""; 10 foreach (PropertyInfo propertyInfo in propertyInfos) 11 { 12 //调用该方法时如果传入true则无法获取非公开的get方法 13 MethodInfo getInfo = propertyInfo.GetGetMethod(true); 14 string getStr = String.Format("Get字段名称:{0} 返回值类型:{1} 参数数量为:{2} MSIL代码长度为:{3} 局部变量数量为:{4};", 15 getInfo.Name, getInfo.ReturnType.ToString(),getInfo.GetParameters().Count(), 16 getInfo.GetMethodBody().GetILAsByteArray().Length,getInfo.GetMethodBody().LocalVariables.Count); 17 MethodInfo setInfo = propertyInfo.GetSetMethod(true); 18 string setStr = String.Format("Set字段名称:{0} 返回值类型:{1} 参数数量为:{2} MSIL代码长度为:{3} 局部变量数量为:{4};", 19 getInfo.Name, getInfo.ReturnType.ToString(), getInfo.GetParameters().Count(), 20 getInfo.GetMethodBody().GetILAsByteArray().Length, getInfo.GetMethodBody().LocalVariables.Count); 21 //调用了set方法将值改变,然后再通过调用get方法获取这个属性的值。 22 setInfo.Invoke(rc, new object[] { 123 }); 23 object obj = getInfo.Invoke(rc, null); 24 string invokeStr = String.Format("方法名:{0} 内部值:{1};", propertyInfo.Name, obj); 25 s += getStr+setStr+ invokeStr; 26 } 27 MessageBox.Show(s); 28 //Get字段名称:get_test1 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 29 //Set字段名称:get_test1 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 30 //方法名:test1 内部值:123; 31 32 //Get字段名称:get_test2 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 33 //Set字段名称:get_test2 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 34 //方法名:test2 内部值:123; 35 36 //Get字段名称:get_test4 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 37 //Set字段名称:get_test4 返回值类型:System.Int32 参数数量为:0 MSIL代码长度为:11 局部变量数量为:1; 38 //方法名:test4 内部值:123; 39 }
12、测试类
1 public class RefClass 2 { 3 private int test3; 4 private int test1{get;set;} 5 protected int test2{get;set;} 6 public int test4{get;set;} 7 8 public string Show(string s) 9 { 10 string a; 11 return s; 12 13 } 14 public static void show2() 15 { } 16 17 public static string show3( string s) 18 { 19 int b; 20 int c; 21 return s; 22 } 23 }

浙公网安备 33010602011771号