C#反射 入门学习 02

      

                                                                      获取Type类型的构造函数

                                                                                     

        前言

                 有了前面的 C#反射 入门学习 01的知识,学习这篇估计是搓搓有余,它教会了我们获取方法的相关信息的两种形式与

              使用反射调用方法, 如果你不会就去看前面的C#反射 入门学习 01 吧!

                在前面的示例中,由于MyClass类型的对象是显示创建的,这样让我们想到了反射技术调用MyClass没有任何优势---

              比普通方式复杂得多。但是如果运行时对象是动态的创建的,反射功能的优势就会显示出来。不做过多讲解,代码注释

              够详细了,有了前面的知识你一定懂的!

               

              注意:我们继续用前面的 MyClass类,但这里我们把它变成MyClassTwo,因为这里的MyClassTwo与前面的

              MyClass稍有修改!

     

              为了方便以后复习,这里折叠了MyClassTwo类

 1  class MyClassTwo
 2     {
 3         int x;
 4         int y;
 5         public MyClassTwo(int i)
 6         {
 7             Console.WriteLine("Constructing MyClassTwo(int)");
 8             this.x=this.y = i;
 9         }
10         public MyClassTwo(int i, int j)
11         {
12             Console.WriteLine("Constructing MyClassTwo(int , int)");
13             this.x = i;
14             this.y = j;
15             Show();
16         }
17         public int Sum()
18         {
19             return x + y;
20         }
21         public bool IsBetween(int i)
22         {
23             if (x < i && i < y)
24             {
25                 return true;
26             }
27             return false;
28         }
29         public void Set(int a, int b)
30         {
31             Console.WriteLine("Inside Set(int,int)");
32             x = a;
33             y = b;
34             Show();
35         }
36         public void Set(double a, double b)
37         {
38             Console.WriteLine("Inside Set(double,double)");
39             x = (int)a;
40             y = (int)b;
41             Show();
42         }
43         public void Show()
44         {
45             Console.WriteLine("valus are  x: " + x + "  y:  " + y);
46         }
47     }
MaClassTwo

 应用程序代码

 1  #region 获取Tyoe对象的构造函数
 2 
 3             Type t = typeof(MyClassTwo);
 4             int val;
 5             //获得构造函数的信息
 6             ConstructorInfo[] ci = t.GetConstructors();
 7             Console.WriteLine("可用的构造函数");//available constructors
 8             foreach (ConstructorInfo c in ci)
 9             {
10                 Console.Write("  "+t.Name+ "  (");
11                 //显示构造函数
12                 ParameterInfo[] pi = c.GetParameters();
13                 for (int i = 0; i < pi.Length; i++)
14                 {
15                     Console.Write(" " + pi[i].ParameterType.Name + "  " + pi[i].Name);//获得调用构造函数里成员的类型
16                     if (i+1<pi.Length)
17                     {
18                         Console.Write(",");
19                     }
20                 }
21                 Console.WriteLine(")");
22             }
23             Console.WriteLine();
24 
25             //找到匹配的构造函数
26             int x;
27             for (x = 0; x < ci.Length; x++)
28             {
29                 ParameterInfo[] pi = ci[x].GetParameters();
30                 if (pi.Length==2)//查找有两个参数的构造函数
31                 {
32                     break;
33                 }
34             }
35             if (x == ci.Length)
36             {
37                 Console.WriteLine("No matching constructor found");
38                 return;
39             }
40             else { Console.WriteLine("Two-parameter constructor found"); }
41 
42             //如果找到带两个参数的构造函数,那么下面的语句实例化一个该类型的对象
43              object[] consargs = new object[2]; 
44              consargs[0] = 10; 
45              consargs[1] = 20;
46              object reflectOb = ci[x].Invoke(consargs); //传给构造函数,并执行reflectOb【MyClassTwo】实例上的方法
47 
48              Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
49              Console.WriteLine("
Invoking methods on reflectOb."); 
50              Console.WriteLine(); 
51             MethodInfo[] mi = t.GetMethods(); 
52  
53             // 调用每个方法
54             foreach (MethodInfo m in mi)
55             {
56                 // 得到的参数
57                 ParameterInfo[] pi = m.GetParameters();
58 
59                 if (m.Name.Equals("Set", StringComparison.Ordinal) &&
60                    pi[0].ParameterType == typeof(int))//比较参数的Type类型
61                 {
62                     // This is Set(int, int). 
63                     object[] obj = new object[2];
64                     obj[0] = 9;
65                     obj[1] = 18;
66                     m.Invoke(reflectOb, obj);
67                 }
68                 else if (m.Name.Equals("Set", StringComparison.Ordinal) &&
69                         pi[0].ParameterType == typeof(double))
70                 {
71                     // This is Set(double, double). 
72                     object[] obj = new object[2];
73                     obj[0] = 1.12;
74                     obj[1] = 23.4;
75                     m.Invoke(reflectOb, obj);
76                 }
77                 else if (m.Name.Equals("Sum", StringComparison.Ordinal))
78                 {
79                     val = (int)m.Invoke(reflectOb, null);
80                     Console.WriteLine("Sum is " + val);
81                 }
82                 else if (m.Name.Equals("IsBetween", StringComparison.Ordinal))
83                 {
84                        object[] obj = new object[1];
85                        obj[0] = 14;
86                        if ((bool)m.Invoke(reflectOb, obj))
87                        Console.WriteLine("14 is between x and y");
88                 }
89                 else if (m.Name.Equals("Show"))
90                 {
91                     m.Invoke(reflectOb, null);
92                 }
93 
94             }
95     //构造函数
96 
97 
98             #endregion

             

                                                           从程序集获得类型

              

              

获得程序集的信息,前提是我们要编辑一个程序集供我们来获取,编辑程序集的代码折叠放下面:

 1  class Demo
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.WriteLine("This is a placeholder."); //占位符
 6         }
 7     }
 8 
 9 
10  class MyClass
11     {
12         int x;
13         int y;
14 
15         public MyClass(int i)
16         {
17             Console.WriteLine("Constructing MyClass(int). ");
18             x = y = i;
19             Show();
20         }
21 
22         public MyClass(int i, int j)
23         {
24             Console.WriteLine("Constructing MyClass(int, int). ");
25             x = i;
26             y = j;
27             Show();
28         }
29 
30         public int Sum()
31         {
32             return x + y;
33         }
34 
35         public bool IsBetween(int i)
36         {
37             if ((x < i) && (i < y)) return true;
38             else return false;
39         }
40 
41         public void Set(int a, int b)
42         {
43             Console.Write("Inside Set(int, int). ");
44             x = a;
45             y = b;
46             Show();
47         }
48 
49         // Overload Set. 
50         public void Set(double a, double b)
51         {
52             Console.Write("Inside Set(double, double). ");
53             x = (int)a;
54             y = (int)b;
55             Show();
56         }
57 
58         public void Show()
59         {
60             Console.WriteLine("Values are x: {0}, y: {1}", x, y);
61         } 
62     }
63 
64 
65 
66 
67 
68   class AnotherClass
69     {
70         string msg;
71 
72         public AnotherClass(string str)
73         {
74             msg = str;
75         }
76 
77         public void Show()
78         {
79             Console.WriteLine(msg);
80         } 
81     }
程序集 .exe

获得程序集的相关信息,首先要创建一个 Assembly对象,它没有定义公有的构造函数,它的对象实例是通过调用类的方法获得的。

这里使用LoadFrom()方法可以加载由文件名指定的程序集,格式:static  Assembly LoadFrom(string  ~.exe)    ~.exe—>程序集文件名

一旦获得了Assembly 类型对象,就可以通过在该对象上调用GetType()方法得到它所定义的类型。格式:Type [] GetType() 它包含了

程序集中的类型,返回值是一个数组!

下面我们就来获得 .exe 里面的信息:

  1   #region 从程序集获得类型
  2 
  3             // 找到一个程序集,确定类型,并创建一个对象使用反射。
  4             int val;
  5 
  6             // Load the MyClasses.exe assembly. 加载MyClasses.exe程序集。
  7             Assembly asm = Assembly.LoadFrom("MyClasses.exe");
  8 
  9             // Discover what types MyClasses.exe contains. 展现MyClasses.exe的类型
 10             Type[] alltypes = asm.GetTypes();
 11             foreach (Type temp in alltypes)
 12                 Console.WriteLine("Found: " + temp.Name);
 13 
 14             
 15             Console.WriteLine();
 16 
 17             // MyClass在这种情况下,使用第一个类
 18             Type t = alltypes[0]; // use first class found 
 19             //后面的技术跟前面 《获取Type对象的构造函数本质一样》
 20             Console.WriteLine("Using: " + t.Name);
 21 
 22             //  获得构造函数的信息。
 23             ConstructorInfo[] ci = t.GetConstructors();
 24 
 25             Console.WriteLine("Available constructors: ");
 26             foreach (ConstructorInfo c in ci)
 27             {
 28                 // 显示返回类型和名称
 29                 Console.Write("   " + t.Name + "(");
 30 
 31                 //  显示参数 
 32                 ParameterInfo[] pi = c.GetParameters();
 33 
 34                 for (int i = 0; i < pi.Length; i++)
 35                 {
 36                     Console.Write(pi[i].ParameterType.Name +
 37                                   " " + pi[i].Name);
 38                     if (i + 1 < pi.Length) Console.Write(", ");
 39                 }
 40 
 41                 Console.WriteLine(")");
 42             }
 43             Console.WriteLine();
 44 
 45             //  找到匹配的构造函数。
 46             int x;
 47 
 48             for (x = 0; x < ci.Length; x++)
 49             {
 50                 ParameterInfo[] pi = ci[x].GetParameters();
 51                 if (pi.Length == 2) break;
 52             }
 53 
 54             if (x == ci.Length)
 55             {
 56                 Console.WriteLine("No matching constructor found.");
 57                 return;
 58             }
 59             else
 60                 Console.WriteLine("Two-parameter constructor found.
");
 61 
 62             //   构造对象
 63             object[] consargs = new object[2];
 64             consargs[0] = 10;
 65             consargs[1] = 20;
 66             object reflectOb = ci[x].Invoke(consargs);
 67 
 68             Console.WriteLine("
Invoking methods on reflectOb.");
 69             Console.WriteLine();
 70             MethodInfo[] mi = t.GetMethods();
 71 
 72             // 调用每一个方法。
 73             foreach (MethodInfo m in mi)
 74             {
 75                 //  得到的参数
 76                 ParameterInfo[] pi = m.GetParameters();
 77 
 78                 if (m.Name.Equals("Set", StringComparison.Ordinal) &&
 79                    pi[0].ParameterType == typeof(int))
 80                 {
 81                     // This is Set(int, int). 
 82                     object[] obj = new object[2];
 83                     obj[0] = 9;
 84                     obj[1] = 18;
 85                     m.Invoke(reflectOb, args);
 86                 }
 87                 else if (m.Name.Equals("Set", StringComparison.Ordinal) &&
 88                    pi[0].ParameterType == typeof(double))
 89                 {
 90                     // This is Set(double, double). 
 91                     object[] obj = new object[2];
 92                     obj[0] = 1.12;
 93                     obj[1] = 23.4;
 94                     m.Invoke(reflectOb, args);
 95                 }
 96                 else if (m.Name.Equals("Sum", StringComparison.Ordinal))
 97                 {
 98                     val = (int)m.Invoke(reflectOb, null);
 99                     Console.WriteLine("sum is " + val);
100                 }
101                 else if (m.Name.Equals("IsBetween", StringComparison.Ordinal))
102                 {
103                     object[] obj = new object[1];
104                     obj[0] = 14;
105                     if ((bool)m.Invoke(reflectOb, args))
106                         Console.WriteLine("14 is between x and y");
107                 }
108                 else if (m.Name.Equals("Show", StringComparison.Ordinal))
109                 {
110                     m.Invoke(reflectOb, null);
111                 }
112             } 
113 
114 
115             #endregion

 说明一点,其实 .dll 文件也是可以的    格式 :Assembly asm = Assembly.LoadFrom("MyClasses.dll");

                                   

                                                       全自动类型查询

前面是我们必须预先知道程序集里类的方法名称,那我们可不可以不必预先知道它的任何信息,同样能调用所需的全部信息?

答案是肯定的,此方法对于可视化设置工具很有用,因为它可以利用系统上所有可用的类型。

程序集还是上面的 MyClasses.exe        直接上应用程序代码。。。

 1            #region 全自动化类型查询【没有假设任何先验知识情况下,利用MyClass】
 2 
 3             int val;
 4             Assembly asm = Assembly.LoadFrom("MyClasses.exe");
 5 
 6             Type[] alltypes = asm.GetTypes();
 7 
 8             Type t = alltypes[0]; // use first class found  ***这里只查看了Demo类哦,别的可以自己去推敲下
 9 
10             Console.WriteLine("Using: " + t.Name);
11 
12             ConstructorInfo[] ci = t.GetConstructors();//获得构造函数
13 
14             // Use first constructor found. 
15             ParameterInfo[] cpi = ci[0].GetParameters();
16             object reflectOb;
17 
18             if (cpi.Length > 0)
19             {
20                 object[] consargs = new object[cpi.Length];
21 
22                 // Initialize args. 
23                 for (int n = 0; n < cpi.Length; n++)
24                     consargs[n] = 10 + n * 20;
25 
26                 // Construct the object. 
27                 reflectOb = ci[0].Invoke(consargs);
28             }
29             else
30                 reflectOb = ci[0].Invoke(null);
31 
32 
33             Console.WriteLine("
Invoking methods on reflectOb.");
34             Console.WriteLine();
35 
36             // Ignore inherited methods. 
37             MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly |
38                                            BindingFlags.Instance |
39                                            BindingFlags.Public);
40 
41             // Invoke each method. 
42             foreach (MethodInfo m in mi)
43             {
44                 Console.WriteLine("Calling {0} ", m.Name);
45 
46                 // Get the parameters. 
47                 ParameterInfo[] pi = m.GetParameters();
48 
49                 // Execute methods. 
50                 switch (pi.Length)
51                 {
52                     case 0: // no args 
53                         if (m.ReturnType == typeof(int))
54                         {
55                             val = (int)m.Invoke(reflectOb, null);
56                             Console.WriteLine("Result is " + val);
57                         }
58                         else if (m.ReturnType == typeof(void))
59                         {
60                             m.Invoke(reflectOb, null);
61                         }
62                         break;
63                     case 1: // one arg 
64                         if (pi[0].ParameterType == typeof(int))
65                         {
66                             object[] obj = new object[1];
67                             obj[0] = 14;
68                             if ((bool)m.Invoke(reflectOb, obj))
69                                 Console.WriteLine("14 is between x and y");
70                             else
71                                 Console.WriteLine("14 is not between x and y");
72                         }
73                         break;
74                     case 2: // two args 
75                         if ((pi[0].ParameterType == typeof(int)) &&
76                            (pi[1].ParameterType == typeof(int)))
77                         {
78                             object[] obj = new object[2];
79                             obj[0] = 9;
80                             obj[1] = 18;
81                             m.Invoke(reflectOb, obj);
82                         }
83                         else if ((pi[0].ParameterType == typeof(double)) &&
84                                 (pi[1].ParameterType == typeof(double)))
85                         {
86                             object[] obj = new object[2];
87                             obj[0] = 1.12;
88                             obj[1] = 23.4;
89                             m.Invoke(reflectOb, obj);
90                         }
91                         break;
92                 }
93                 Console.WriteLine();
94             } 
95 
96             #endregion
在没有任何先验知识情况下,我们如何利用MyClasses类里的信息!

反射暂时学到这里, 做为一个入门者,估计需求供用了!

原文地址:https://www.cnblogs.com/izhiniao/p/3666382.html