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 ...
随机推荐
- 为什么每个程序员都应该用Mac OS X?
1.Mac OS X 是基于 Unix 的.这一点太重要了,尤其是对开发人员,至少对于我来说很重要,这意味着Unix 下一堆好用的工具都可以随手捡到.如果你是个 windows 开发人员,我想你会在 ...
- Java之旅(一)---说说“异常”那些事
从開始学习VB,就听说过"异常",认为异常处理就是加上try..catch,不让错误抛出给用户,到此为止,不要再往下问了,再问也不会了.这就是那时候的理解.如今随时项目经验的 ...
- WinRT Toolkit 介绍--Control篇
WinRT toolkit是组针对Windows Runtime XAML开发的一系列Control,extension和helper类.它和Windows Phone Toolkit一样,也是由很多 ...
- mybatis级联查询
1.定义四个实体.User Role Privilege Resource,他们之间的对于关系为 2.需求:我通过用户名username查找出该用户对应的角色以及角色对应的权限和资源 3 ...
- Java多线程之非线程安全
在Java多线程中我会重点总结五个如下的技术点: 1.非线程安全是如何出现的 2.synchronized对象监视器为Objec时的使用 3.synchronized对象监视器为Class时的使用 4 ...
- java-输出格式
https://docs.oracle.com/javase/tutorial/java/data/numberformat.html Formatting Numeric Print Output ...
- Dapper 基础用法
Dapper是.Net下的一个简单orm框架,具有以下特点: 1.简单,只需要一个文件即可(SqlMapper.cs) 2.快速,下面是一个查询结果集在500以上的运行速度对比 3.不要求特定的db ...
- Chrome Firefox 自定义背景色
Chrome有个自定义背景色的文件 Custom.css 默认里面什么字都没写 html, body {background-color: #e0dcc0!important;} 这个颜色 ...
- TabSpec和TabHost实例
TabSpec与TabHost TabHost相当于浏览器中浏览器分布的集合,而Tabspec则相当于浏览器中的每一个分页面.d在Android中,每一个TabSpec分布可以是一个组件,也可以是一个 ...
- 数学之路(3)-机器学习(3)-机器学习算法-SVM[9]
我们应用SVM的非线性分类功能对手写数字进行识别,我们在这应用poly做为非线性核 svm = mlpy.LibSvm(svm_type='c_svc', kernel_type='poly',gam ...