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 ...
随机推荐
- http协议与http代理
TCP/IP协议族 TCP/IP(Transmission Control Protocol/InternetProtocol.传输控制协议/网际协议)是用于计算机通信的一个协议族. TCP/IP协议 ...
- C#中继承,集合(Eleventh day)
又到了总结知识的时间,今天在云和学院继续学习了继承的一些运用,和集合的运用.下面就总结下来吧 理论: 显示调用父类的构造方法,关键字: base:构造函数不能被继承:子类对象被实例化的时候会先去主动的 ...
- Enze frist day
今天是我来到云和学院正式开班上课的第一天,我选择学习的科目是.net.因为.net我在学校的时候接触过一些,所以我想要更加深入的去学习.我觉得一个学生在学习上最怕的是没有遇到一位负责任的好老师,但幸运 ...
- quartz搭建与应用
1.添加依赖 依赖包括Quartz和logback <dependencies> <dependency> <groupId>org.quartz-schedule ...
- 设计模式值六大原则——里氏替换原则(LSP)
里氏替换原则(Liskov Substitution Principel)是解决继承带来的问题. 继承的优点: 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性: 提高代码的重用性: 子类 ...
- Python每日一练(2):找出html中的所有链接(Xpath、正则两个版本)
要在hrml文件中找出特定的内容,首先需要观察该内容是什么东西,在什么位置,这样才能找出来. 假设html的文件名称是:"1.html".href属性全都在a标签里. 正则版: # ...
- 【转】C++常见错误大全
原文转自:http://hi.baidu.com/qiou2719/item/b9eed949130ff50ec0161331 C++常见错误大全 0. XXXX "is not a cla ...
- Identity-修改Error错误提示为中文
第一步:重写IdentityErrorDescriber public class CustomIdentityErrorDescriber : IdentityErrorDescriber ...
- EAN-13 条码(又称GTIN-13 条码)
EAN全名为European Article Number(欧洲商品条码),在1977年时由欧洲几个主要工业国家共同发展出来的,后来变成国际商品条码系统.台湾在1985年加入EAN会员,现在我们买东西 ...
- boost库学习随记六:使用同步定时器、异步定时器、bind、成员函数回调处理、多线程的同步处理示例等
一.使用同步定时器 这个示例程序通过展示如何在一个定时器执行一个阻塞等待. //makefile #-------------------------------------------------- ...