zoukankan      html  css  js  c++  java
  • 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类里的信息!

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

  • 相关阅读:
    Selenium WebDriver-actionchain模拟键盘左键长按
    Selenium WebDriver-actionchain模拟鼠标右键操作
    CSS3 box-sizing:content-box | border-box
    gulp 使用指南
    MAC 使用指南
    移动端布局Rem
    JS面向对象编程
    webstorm 使用指南
    js 获取 touch length
    css 内容居中
  • 原文地址:https://www.cnblogs.com/izhiniao/p/3666382.html
Copyright © 2011-2022 走看看