获取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 = ; i < pi.Length; i++)
  14. {
  15. Console.Write(" " + pi[i].ParameterType.Name + " " + pi[i].Name);//获得调用构造函数里成员的类型
  16. if (i+<pi.Length)
  17. {
  18. Console.Write(",");
  19. }
  20. }
  21. Console.WriteLine(")");
  22. }
  23. Console.WriteLine();
  24.  
  25. //找到匹配的构造函数
  26. int x;
  27. for (x = ; x < ci.Length; x++)
  28. {
  29. ParameterInfo[] pi = ci[x].GetParameters();
  30. if (pi.Length==)//查找有两个参数的构造函数
  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[];
  44. consargs[] = ;
  45. consargs[] = ;
  46. object reflectOb = ci[x].Invoke(consargs); //传给构造函数,并执行reflectOb【MyClassTwo】实例上的方法
  47.  
  48. Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
  49. Console.WriteLine("\nInvoking 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[].ParameterType == typeof(int))//比较参数的Type类型
  61. {
  62. // This is Set(int, int).
  63. object[] obj = new object[];
  64. obj[] = ;
  65. obj[] = ;
  66. m.Invoke(reflectOb, obj);
  67. }
  68. else if (m.Name.Equals("Set", StringComparison.Ordinal) &&
  69. pi[].ParameterType == typeof(double))
  70. {
  71. // This is Set(double, double).
  72. object[] obj = new object[];
  73. obj[] = 1.12;
  74. obj[] = 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[];
  85. obj[] = ;
  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. #endregion

  从程序集获得类型

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

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

程序集 .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. Console.WriteLine();
  15.  
  16. // MyClass在这种情况下,使用第一个类
  17. Type t = alltypes[]; // use first class found
  18. //后面的技术跟前面 《获取Type对象的构造函数本质一样》
  19. Console.WriteLine("Using: " + t.Name);
  20.  
  21. // 获得构造函数的信息。
  22. ConstructorInfo[] ci = t.GetConstructors();
  23.  
  24. Console.WriteLine("Available constructors: ");
  25. foreach (ConstructorInfo c in ci)
  26. {
  27. // 显示返回类型和名称
  28. Console.Write(" " + t.Name + "(");
  29.  
  30. // 显示参数
  31. ParameterInfo[] pi = c.GetParameters();
  32.  
  33. for (int i = ; i < pi.Length; i++)
  34. {
  35. Console.Write(pi[i].ParameterType.Name +
  36. " " + pi[i].Name);
  37. if (i + < pi.Length) Console.Write(", ");
  38. }
  39.  
  40. Console.WriteLine(")");
  41. }
  42. Console.WriteLine();
  43.  
  44. // 找到匹配的构造函数。
  45. int x;
  46.  
  47. for (x = ; x < ci.Length; x++)
  48. {
  49. ParameterInfo[] pi = ci[x].GetParameters();
  50. if (pi.Length == ) break;
  51. }
  52.  
  53. if (x == ci.Length)
  54. {
  55. Console.WriteLine("No matching constructor found.");
  56. return;
  57. }
  58. else
  59. Console.WriteLine("Two-parameter constructor found.\n");
  60.  
  61. // 构造对象
  62. object[] consargs = new object[];
  63. consargs[] = ;
  64. consargs[] = ;
  65. object reflectOb = ci[x].Invoke(consargs);
  66.  
  67. Console.WriteLine("\nInvoking methods on reflectOb.");
  68. Console.WriteLine();
  69. MethodInfo[] mi = t.GetMethods();
  70.  
  71. // 调用每一个方法。
  72. foreach (MethodInfo m in mi)
  73. {
  74. // 得到的参数
  75. ParameterInfo[] pi = m.GetParameters();
  76.  
  77. if (m.Name.Equals("Set", StringComparison.Ordinal) &&
  78. pi[].ParameterType == typeof(int))
  79. {
  80. // This is Set(int, int).
  81. object[] obj = new object[];
  82. obj[] = ;
  83. obj[] = ;
  84. m.Invoke(reflectOb, args);
  85. }
  86. else if (m.Name.Equals("Set", StringComparison.Ordinal) &&
  87. pi[].ParameterType == typeof(double))
  88. {
  89. // This is Set(double, double).
  90. object[] obj = new object[];
  91. obj[] = 1.12;
  92. obj[] = 23.4;
  93. m.Invoke(reflectOb, args);
  94. }
  95. else if (m.Name.Equals("Sum", StringComparison.Ordinal))
  96. {
  97. val = (int)m.Invoke(reflectOb, null);
  98. Console.WriteLine("sum is " + val);
  99. }
  100. else if (m.Name.Equals("IsBetween", StringComparison.Ordinal))
  101. {
  102. object[] obj = new object[];
  103. obj[] = ;
  104. if ((bool)m.Invoke(reflectOb, args))
  105. Console.WriteLine("14 is between x and y");
  106. }
  107. else if (m.Name.Equals("Show", StringComparison.Ordinal))
  108. {
  109. m.Invoke(reflectOb, null);
  110. }
  111. }
  112.  
  113. #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[]; // 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[].GetParameters();
  16. object reflectOb;
  17.  
  18. if (cpi.Length > )
  19. {
  20. object[] consargs = new object[cpi.Length];
  21.  
  22. // Initialize args.
  23. for (int n = ; n < cpi.Length; n++)
  24. consargs[n] = + n * ;
  25.  
  26. // Construct the object.
  27. reflectOb = ci[].Invoke(consargs);
  28. }
  29. else
  30. reflectOb = ci[].Invoke(null);
  31.  
  32. Console.WriteLine("\nInvoking methods on reflectOb.");
  33. Console.WriteLine();
  34.  
  35. // Ignore inherited methods.
  36. MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly |
  37. BindingFlags.Instance |
  38. BindingFlags.Public);
  39.  
  40. // Invoke each method.
  41. foreach (MethodInfo m in mi)
  42. {
  43. Console.WriteLine("Calling {0} ", m.Name);
  44.  
  45. // Get the parameters.
  46. ParameterInfo[] pi = m.GetParameters();
  47.  
  48. // Execute methods.
  49. switch (pi.Length)
  50. {
  51. case : // no args
  52. if (m.ReturnType == typeof(int))
  53. {
  54. val = (int)m.Invoke(reflectOb, null);
  55. Console.WriteLine("Result is " + val);
  56. }
  57. else if (m.ReturnType == typeof(void))
  58. {
  59. m.Invoke(reflectOb, null);
  60. }
  61. break;
  62. case : // one arg
  63. if (pi[].ParameterType == typeof(int))
  64. {
  65. object[] obj = new object[];
  66. obj[] = ;
  67. if ((bool)m.Invoke(reflectOb, obj))
  68. Console.WriteLine("14 is between x and y");
  69. else
  70. Console.WriteLine("14 is not between x and y");
  71. }
  72. break;
  73. case : // two args
  74. if ((pi[].ParameterType == typeof(int)) &&
  75. (pi[].ParameterType == typeof(int)))
  76. {
  77. object[] obj = new object[];
  78. obj[] = ;
  79. obj[] = ;
  80. m.Invoke(reflectOb, obj);
  81. }
  82. else if ((pi[].ParameterType == typeof(double)) &&
  83. (pi[].ParameterType == typeof(double)))
  84. {
  85. object[] obj = new object[];
  86. obj[] = 1.12;
  87. obj[] = 23.4;
  88. m.Invoke(reflectOb, obj);
  89. }
  90. break;
  91. }
  92. Console.WriteLine();
  93. }
  94.  
  95. #endregion

在没有任何先验知识情况下,我们如何利用MyClasses类里的信息!

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

C#反射 入门学习 02的更多相关文章

  1. C#反射 入门学习 01

    前言     获取方法的相关信息的两种形式 反射是一种允许用户获得类信息的C#功能,Type对象映射它代表的底层对象: 在.Net 中, 一旦获得了Type对象,就可以使用GetMethods()方法 ...

  2. Matlab2015入门学习02

    1. 续行符 ... 当物理的一行之内写不下时, 在 物理行的结尾加上三个小黑点 >>跟在运算符之后,可以不留space空格 >>跟在数字之后,若不留白space,出错; 留一 ...

  3. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  4. opengl入门学习

    OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...

  5. OpenGL入门学习(转载)

    说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...

  6. Android Testing学习02 HelloTesting 项目建立与执行

    Android Testing学习02 HelloTesting 项目建立与执行 Android测试,分为待测试的项目和测试项目,这两个项目会生成两个独立的apk,但是内部,它们会共享同一个进程. 下 ...

  7. Aho-Corasick算法、多模正则匹配、Snort入门学习

    希望解决的问题 . 在一些高流量.高IO的WAF中,是如何对规则库(POST.GET)中的字符串进行多正则匹配的,是单条轮询执行,还是多模式并发执行 . Snort是怎么组织.匹配高达上千条的正则规则 ...

  8. OpenGL入门学习(转)

    OpenGL入门学习 http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html 说起编程作图,大概还有很多人想起TC的#includ ...

  9. SpringMVC入门学习(二)

    SpringMVC入门学习(二) ssm框架 springMVC  在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...

随机推荐

  1. 百度——LBS.云 v2.0——云存储的POI创建和删除--Android 源码

    如有疑问请联系:QQ936467727 需要注意的几点问题: 1.密钥是http://lbsyun.baidu.com/apiconsole/key申请的,密钥类型是浏览器端 2.geotable_i ...

  2. C# Best Practices - Handling Strings

    Features Strings Are Immutable. A String Is a Reference Type Value Type Store their data directly Ex ...

  3. 加特殊符号星号斜杠反斜杠/* \ */ !important等让css实现兼容各个浏览器的技巧的代码

       在编写css样式表的时候常常会碰到一写浏览器兼容的问题,象是不同内核的浏览器显示就不一定相同,不同版本的的浏览器也会产生上下兼容的问题,如何解决这些问题成了我们苦恼的问题,如果你对css hac ...

  4. 第一个processing程序(2016-01-15)

    前几天下载和安装了最新的 processing,今天试一下,哈哈,真是简单之极啊,果然是给非程序员使用的,现在,我也是非程序员了.

  5. Javah生成JNI头文件

    首先确保java的环境变量配置好了. 1:打开cmd 进入doc命令窗口: 进入class所在目录,我的class是在F:\summerVacation\ndkhelloworld\bin\class ...

  6. Node.js学习笔记1(简介)

            1.什么是Node.js?         Node.js,或者 Node,是一个可以让 JavaScript 运行在服务器端的平台.它可以让 JavaScript 脱离浏览器的束缚运 ...

  7. VC++非MFC项目中如何使用TRACE宏

    记得原来尝试学MFC的时候觉得有一个TRACE可以在Debug时向VS的调试输出窗口输出字串符,用来调试时跟踪变量很方便. 然则如果不是MFC项目或者ATL的项目的话是不能使用这个宏的.这时有一个没有 ...

  8. 为joomla加入�下拉菜单的方法

    用 Joomla! 建站的大多数站长都须要在站点前台使用下拉菜单(dropdown menu),或者叫弹出菜单(slide menu),由于这样能够在有限的页面空间上公布很多其它的导航菜单,而且能够进 ...

  9. QT 入门 -QApplication QPushButton QDialog Ui类型的手工使用

    QT 1.工具 assistant  帮助文档 qtconfig  QT配置工具 qmake     QT的make与项目文件智能创建工具 uic          UI界面的设计文件的编译工具 mo ...

  10. AWS要进入中国了

    去年底就开始有这个传言见诸于某些媒体,说网站支持中文了要进中国了,也有说这不代表什么是谣言 这几天又听到有消息说比较靠谱就半年内的事儿 其实如果没有政策阻碍的话进中国是迟早的事情,原因如下 Amazo ...