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 ...
随机推荐
- word中创建文本框
word中创建文本框 在插入中点击"文本框"选项卡,例如以下图所看到的: 手工加入自己想要的文本框格式,然后选择所创建的文本框,在工具栏处会发现多了一 ...
- UISegmentedControl(分页控制器) AND UISlider(滑块控制器)
- (void)viewDidLoad { [super viewDidLoad]; UIImageView * animatedImageView = [[UIImageView alloc]ini ...
- 在C#中使用 Win32 和其他库
C# 用户经常提出两个问题:“我为什么要另外编写代码来使用内置于 Windows® 中的功能?在框架中为什么没有相应的内容可以为我完成这一任务?”当框架小组构建他们的 .NET 部分时,他们评估了为使 ...
- android 基础学习图片六progross
加载进度条应用
- 「C」 数组、字符串、指针
一.数组 (一)数组 概念:用来存储一组数据的构造数据类型 特点:只能存放一种类型的数据,如全部是int型或者全部是char型,数组里的数据成为元素. (二)数组的定义 格式: 类型 数组名[元素个数 ...
- BZOJ 1567: [JSOI2008]Blue Mary的战役地图( 二分答案 + hash )
二分答案, 然后用哈希去判断... ------------------------------------------------------------------------- #include ...
- 关于Ubuntu远程ssh连接失败的问题
在做机器人项目的时候,用的是Ubuntu的linux,跟之前的CentOS的操作命令有一点差别,就比如防火墙的名字,在Ubuntu系统中叫什么ufw,真是有点不好接受. 为了能模拟环境,我又弄了一台电 ...
- OSX/iOS 播放系统声音
方法1: 系统会自带了些声音,有时候一些操作用必要自己播放一下声音提醒一下,用bash的直接say something就ok了,写代码的时候呢?原来很简单的,一句: [[NSSound soundNa ...
- ASP.NET MVC5 学习笔记-1 控制器、路由、返回类型、选择器、过滤器
[TOC] 1. Action 1.1 新建项目 新建项目->Web->Asp.net Web应用程序,选择MVC,选择添加测试. 在解决方案上右键,选择"管理NuGet程序包& ...
- 一次搞定cocos2d-x的 Android.mk 文件
cocos2d-x 打 android 包时要修改 Android.mk 文件,但每次修改很麻烦,如果源文件很多的话就坑死了,也可以写一个脚本来自动生成这个文件,但每次还要重新生成一下,将其修改下面的 ...