C#反射 入门学习 02
获取Type类型的构造函数
前言
有了前面的 C#反射 入门学习 01的知识,学习这篇估计是搓搓有余,它教会了我们获取方法的相关信息的两种形式与
使用反射调用方法, 如果你不会就去看前面的C#反射 入门学习 01吧!
在前面的示例中,由于MyClass类型的对象是显示创建的,这样让我们想到了反射技术调用MyClass没有任何优势---
比普通方式复杂得多。但是如果运行时对象是动态的创建的,反射功能的优势就会显示出来。不做过多讲解,代码注释
够详细了,有了前面的知识你一定懂的!
注意:我们继续用前面的 MyClass类,但这里我们把它变成MyClassTwo,因为这里的MyClassTwo与前面的
MyClass稍有修改!
为了方便以后复习,这里折叠了MyClassTwo类
- class MyClassTwo
- {
- int x;
- int y;
- public MyClassTwo(int i)
- {
- Console.WriteLine("Constructing MyClassTwo(int)");
- this.x=this.y = i;
- }
- public MyClassTwo(int i, int j)
- {
- Console.WriteLine("Constructing MyClassTwo(int , int)");
- this.x = i;
- this.y = j;
- Show();
- }
- public int Sum()
- {
- return x + y;
- }
- public bool IsBetween(int i)
- {
- if (x < i && i < y)
- {
- return true;
- }
- return false;
- }
- public void Set(int a, int b)
- {
- Console.WriteLine("Inside Set(int,int)");
- x = a;
- y = b;
- Show();
- }
- public void Set(double a, double b)
- {
- Console.WriteLine("Inside Set(double,double)");
- x = (int)a;
- y = (int)b;
- Show();
- }
- public void Show()
- {
- Console.WriteLine("valus are x: " + x + " y: " + y);
- }
- }
MaClassTwo
应用程序代码
- #region 获取Tyoe对象的构造函数
- Type t = typeof(MyClassTwo);
- int val;
- //获得构造函数的信息
- ConstructorInfo[] ci = t.GetConstructors();
- Console.WriteLine("可用的构造函数");//available constructors
- foreach (ConstructorInfo c in ci)
- {
- Console.Write(" "+t.Name+ " (");
- //显示构造函数
- ParameterInfo[] pi = c.GetParameters();
- for (int i = ; i < pi.Length; i++)
- {
- Console.Write(" " + pi[i].ParameterType.Name + " " + pi[i].Name);//获得调用构造函数里成员的类型
- if (i+<pi.Length)
- {
- Console.Write(",");
- }
- }
- Console.WriteLine(")");
- }
- Console.WriteLine();
- //找到匹配的构造函数
- int x;
- for (x = ; x < ci.Length; x++)
- {
- ParameterInfo[] pi = ci[x].GetParameters();
- if (pi.Length==)//查找有两个参数的构造函数
- {
- break;
- }
- }
- if (x == ci.Length)
- {
- Console.WriteLine("No matching constructor found");
- return;
- }
- else { Console.WriteLine("Two-parameter constructor found"); }
- //如果找到带两个参数的构造函数,那么下面的语句实例化一个该类型的对象
- object[] consargs = new object[];
- consargs[] = ;
- consargs[] = ;
- object reflectOb = ci[x].Invoke(consargs); //传给构造函数,并执行reflectOb【MyClassTwo】实例上的方法
- Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
- Console.WriteLine("\nInvoking methods on reflectOb.");
- Console.WriteLine();
- MethodInfo[] mi = t.GetMethods();
- // 调用每个方法
- foreach (MethodInfo m in mi)
- {
- // 得到的参数
- ParameterInfo[] pi = m.GetParameters();
- if (m.Name.Equals("Set", StringComparison.Ordinal) &&
- pi[].ParameterType == typeof(int))//比较参数的Type类型
- {
- // This is Set(int, int).
- object[] obj = new object[];
- obj[] = ;
- obj[] = ;
- m.Invoke(reflectOb, obj);
- }
- else if (m.Name.Equals("Set", StringComparison.Ordinal) &&
- pi[].ParameterType == typeof(double))
- {
- // This is Set(double, double).
- object[] obj = new object[];
- obj[] = 1.12;
- obj[] = 23.4;
- m.Invoke(reflectOb, obj);
- }
- else if (m.Name.Equals("Sum", StringComparison.Ordinal))
- {
- val = (int)m.Invoke(reflectOb, null);
- Console.WriteLine("Sum is " + val);
- }
- else if (m.Name.Equals("IsBetween", StringComparison.Ordinal))
- {
- object[] obj = new object[];
- obj[] = ;
- if ((bool)m.Invoke(reflectOb, obj))
- Console.WriteLine("14 is between x and y");
- }
- else if (m.Name.Equals("Show"))
- {
- m.Invoke(reflectOb, null);
- }
- }
- //构造函数
- #endregion
从程序集获得类型
获得程序集的信息,前提是我们要编辑一个程序集供我们来获取,编辑程序集的代码折叠放下面:
- class Demo
- {
- static void Main(string[] args)
- {
- Console.WriteLine("This is a placeholder."); //占位符
- }
- }
- class MyClass
- {
- int x;
- int y;
- public MyClass(int i)
- {
- Console.WriteLine("Constructing MyClass(int). ");
- x = y = i;
- Show();
- }
- public MyClass(int i, int j)
- {
- Console.WriteLine("Constructing MyClass(int, int). ");
- x = i;
- y = j;
- Show();
- }
- public int Sum()
- {
- return x + y;
- }
- public bool IsBetween(int i)
- {
- if ((x < i) && (i < y)) return true;
- else return false;
- }
- public void Set(int a, int b)
- {
- Console.Write("Inside Set(int, int). ");
- x = a;
- y = b;
- Show();
- }
- // Overload Set.
- public void Set(double a, double b)
- {
- Console.Write("Inside Set(double, double). ");
- x = (int)a;
- y = (int)b;
- Show();
- }
- public void Show()
- {
- Console.WriteLine("Values are x: {0}, y: {1}", x, y);
- }
- }
- class AnotherClass
- {
- string msg;
- public AnotherClass(string str)
- {
- msg = str;
- }
- public void Show()
- {
- Console.WriteLine(msg);
- }
- }
程序集 .exe
获得程序集的相关信息,首先要创建一个 Assembly对象,它没有定义公有的构造函数,它的对象实例是通过调用类的方法获得的。
这里使用LoadFrom()方法可以加载由文件名指定的程序集,格式:static Assembly LoadFrom(string ~.exe) ~.exe—>程序集文件名
一旦获得了Assembly 类型对象,就可以通过在该对象上调用GetType()方法得到它所定义的类型。格式:Type [] GetType() 它包含了
程序集中的类型,返回值是一个数组!
下面我们就来获得 .exe 里面的信息:
- #region 从程序集获得类型
- // 找到一个程序集,确定类型,并创建一个对象使用反射。
- int val;
- // Load the MyClasses.exe assembly. 加载MyClasses.exe程序集。
- Assembly asm = Assembly.LoadFrom("MyClasses.exe");
- // Discover what types MyClasses.exe contains. 展现MyClasses.exe的类型
- Type[] alltypes = asm.GetTypes();
- foreach (Type temp in alltypes)
- Console.WriteLine("Found: " + temp.Name);
- Console.WriteLine();
- // MyClass在这种情况下,使用第一个类
- Type t = alltypes[]; // use first class found
- //后面的技术跟前面 《获取Type对象的构造函数本质一样》
- Console.WriteLine("Using: " + t.Name);
- // 获得构造函数的信息。
- ConstructorInfo[] ci = t.GetConstructors();
- Console.WriteLine("Available constructors: ");
- foreach (ConstructorInfo c in ci)
- {
- // 显示返回类型和名称
- Console.Write(" " + t.Name + "(");
- // 显示参数
- ParameterInfo[] pi = c.GetParameters();
- for (int i = ; i < pi.Length; i++)
- {
- Console.Write(pi[i].ParameterType.Name +
- " " + pi[i].Name);
- if (i + < pi.Length) Console.Write(", ");
- }
- Console.WriteLine(")");
- }
- Console.WriteLine();
- // 找到匹配的构造函数。
- int x;
- for (x = ; x < ci.Length; x++)
- {
- ParameterInfo[] pi = ci[x].GetParameters();
- if (pi.Length == ) break;
- }
- if (x == ci.Length)
- {
- Console.WriteLine("No matching constructor found.");
- return;
- }
- else
- Console.WriteLine("Two-parameter constructor found.\n");
- // 构造对象
- object[] consargs = new object[];
- consargs[] = ;
- consargs[] = ;
- object reflectOb = ci[x].Invoke(consargs);
- Console.WriteLine("\nInvoking methods on reflectOb.");
- Console.WriteLine();
- MethodInfo[] mi = t.GetMethods();
- // 调用每一个方法。
- foreach (MethodInfo m in mi)
- {
- // 得到的参数
- ParameterInfo[] pi = m.GetParameters();
- if (m.Name.Equals("Set", StringComparison.Ordinal) &&
- pi[].ParameterType == typeof(int))
- {
- // This is Set(int, int).
- object[] obj = new object[];
- obj[] = ;
- obj[] = ;
- m.Invoke(reflectOb, args);
- }
- else if (m.Name.Equals("Set", StringComparison.Ordinal) &&
- pi[].ParameterType == typeof(double))
- {
- // This is Set(double, double).
- object[] obj = new object[];
- obj[] = 1.12;
- obj[] = 23.4;
- m.Invoke(reflectOb, args);
- }
- else if (m.Name.Equals("Sum", StringComparison.Ordinal))
- {
- val = (int)m.Invoke(reflectOb, null);
- Console.WriteLine("sum is " + val);
- }
- else if (m.Name.Equals("IsBetween", StringComparison.Ordinal))
- {
- object[] obj = new object[];
- obj[] = ;
- if ((bool)m.Invoke(reflectOb, args))
- Console.WriteLine("14 is between x and y");
- }
- else if (m.Name.Equals("Show", StringComparison.Ordinal))
- {
- m.Invoke(reflectOb, null);
- }
- }
- #endregion
说明一点,其实 .dll 文件也是可以的 格式 :Assembly asm = Assembly.LoadFrom("MyClasses.dll");
全自动类型查询
前面是我们必须预先知道程序集里类的方法名称,那我们可不可以不必预先知道它的任何信息,同样能调用所需的全部信息?
答案是肯定的,此方法对于可视化设置工具很有用,因为它可以利用系统上所有可用的类型。
程序集还是上面的 MyClasses.exe 直接上应用程序代码。。。
- #region 全自动化类型查询【没有假设任何先验知识情况下,利用MyClass】
- int val;
- Assembly asm = Assembly.LoadFrom("MyClasses.exe");
- Type[] alltypes = asm.GetTypes();
- Type t = alltypes[]; // use first class found ***这里只查看了Demo类哦,别的可以自己去推敲下
- Console.WriteLine("Using: " + t.Name);
- ConstructorInfo[] ci = t.GetConstructors();//获得构造函数
- // Use first constructor found.
- ParameterInfo[] cpi = ci[].GetParameters();
- object reflectOb;
- if (cpi.Length > )
- {
- object[] consargs = new object[cpi.Length];
- // Initialize args.
- for (int n = ; n < cpi.Length; n++)
- consargs[n] = + n * ;
- // Construct the object.
- reflectOb = ci[].Invoke(consargs);
- }
- else
- reflectOb = ci[].Invoke(null);
- Console.WriteLine("\nInvoking methods on reflectOb.");
- Console.WriteLine();
- // Ignore inherited methods.
- MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly |
- BindingFlags.Instance |
- BindingFlags.Public);
- // Invoke each method.
- foreach (MethodInfo m in mi)
- {
- Console.WriteLine("Calling {0} ", m.Name);
- // Get the parameters.
- ParameterInfo[] pi = m.GetParameters();
- // Execute methods.
- switch (pi.Length)
- {
- case : // no args
- if (m.ReturnType == typeof(int))
- {
- val = (int)m.Invoke(reflectOb, null);
- Console.WriteLine("Result is " + val);
- }
- else if (m.ReturnType == typeof(void))
- {
- m.Invoke(reflectOb, null);
- }
- break;
- case : // one arg
- if (pi[].ParameterType == typeof(int))
- {
- object[] obj = new object[];
- obj[] = ;
- if ((bool)m.Invoke(reflectOb, obj))
- Console.WriteLine("14 is between x and y");
- else
- Console.WriteLine("14 is not between x and y");
- }
- break;
- case : // two args
- if ((pi[].ParameterType == typeof(int)) &&
- (pi[].ParameterType == typeof(int)))
- {
- object[] obj = new object[];
- obj[] = ;
- obj[] = ;
- m.Invoke(reflectOb, obj);
- }
- else if ((pi[].ParameterType == typeof(double)) &&
- (pi[].ParameterType == typeof(double)))
- {
- object[] obj = new object[];
- obj[] = 1.12;
- obj[] = 23.4;
- m.Invoke(reflectOb, obj);
- }
- break;
- }
- Console.WriteLine();
- }
- #endregion
在没有任何先验知识情况下,我们如何利用MyClasses类里的信息!
反射暂时学到这里, 做为一个入门者,估计需求供用了!
C#反射 入门学习 02的更多相关文章
- C#反射 入门学习 01
前言 获取方法的相关信息的两种形式 反射是一种允许用户获得类信息的C#功能,Type对象映射它代表的底层对象: 在.Net 中, 一旦获得了Type对象,就可以使用GetMethods()方法 ...
- Matlab2015入门学习02
1. 续行符 ... 当物理的一行之内写不下时, 在 物理行的结尾加上三个小黑点 >>跟在运算符之后,可以不留space空格 >>跟在数字之后,若不留白space,出错; 留一 ...
- 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习
反射实现Model修改前后的内容对比 在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...
- opengl入门学习
OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...
- OpenGL入门学习(转载)
说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...
- Android Testing学习02 HelloTesting 项目建立与执行
Android Testing学习02 HelloTesting 项目建立与执行 Android测试,分为待测试的项目和测试项目,这两个项目会生成两个独立的apk,但是内部,它们会共享同一个进程. 下 ...
- Aho-Corasick算法、多模正则匹配、Snort入门学习
希望解决的问题 . 在一些高流量.高IO的WAF中,是如何对规则库(POST.GET)中的字符串进行多正则匹配的,是单条轮询执行,还是多模式并发执行 . Snort是怎么组织.匹配高达上千条的正则规则 ...
- OpenGL入门学习(转)
OpenGL入门学习 http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html 说起编程作图,大概还有很多人想起TC的#includ ...
- SpringMVC入门学习(二)
SpringMVC入门学习(二) ssm框架 springMVC 在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...
随机推荐
- 百度——LBS.云 v2.0——云存储的POI创建和删除--Android 源码
如有疑问请联系:QQ936467727 需要注意的几点问题: 1.密钥是http://lbsyun.baidu.com/apiconsole/key申请的,密钥类型是浏览器端 2.geotable_i ...
- C# Best Practices - Handling Strings
Features Strings Are Immutable. A String Is a Reference Type Value Type Store their data directly Ex ...
- 加特殊符号星号斜杠反斜杠/* \ */ !important等让css实现兼容各个浏览器的技巧的代码
在编写css样式表的时候常常会碰到一写浏览器兼容的问题,象是不同内核的浏览器显示就不一定相同,不同版本的的浏览器也会产生上下兼容的问题,如何解决这些问题成了我们苦恼的问题,如果你对css hac ...
- 第一个processing程序(2016-01-15)
前几天下载和安装了最新的 processing,今天试一下,哈哈,真是简单之极啊,果然是给非程序员使用的,现在,我也是非程序员了.
- Javah生成JNI头文件
首先确保java的环境变量配置好了. 1:打开cmd 进入doc命令窗口: 进入class所在目录,我的class是在F:\summerVacation\ndkhelloworld\bin\class ...
- Node.js学习笔记1(简介)
1.什么是Node.js? Node.js,或者 Node,是一个可以让 JavaScript 运行在服务器端的平台.它可以让 JavaScript 脱离浏览器的束缚运 ...
- VC++非MFC项目中如何使用TRACE宏
记得原来尝试学MFC的时候觉得有一个TRACE可以在Debug时向VS的调试输出窗口输出字串符,用来调试时跟踪变量很方便. 然则如果不是MFC项目或者ATL的项目的话是不能使用这个宏的.这时有一个没有 ...
- 为joomla加入�下拉菜单的方法
用 Joomla! 建站的大多数站长都须要在站点前台使用下拉菜单(dropdown menu),或者叫弹出菜单(slide menu),由于这样能够在有限的页面空间上公布很多其它的导航菜单,而且能够进 ...
- QT 入门 -QApplication QPushButton QDialog Ui类型的手工使用
QT 1.工具 assistant 帮助文档 qtconfig QT配置工具 qmake QT的make与项目文件智能创建工具 uic UI界面的设计文件的编译工具 mo ...
- AWS要进入中国了
去年底就开始有这个传言见诸于某些媒体,说网站支持中文了要进中国了,也有说这不代表什么是谣言 这几天又听到有消息说比较靠谱就半年内的事儿 其实如果没有政策阻碍的话进中国是迟早的事情,原因如下 Amazo ...