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         }
View Code

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         }
set修改值

 

该类型是否是类
     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         }
View Code

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         }
View Code

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   }
RefClass

 

posted @ 2017-07-09 22:37  高金顶  阅读(151)  评论(0)    收藏  举报