反射是.net中的高级功能之一,利用反射可以实现许多以前看来匪夷所思的功能,下面是我看了《programming c#》(oreilly)之后对于反射的一点实践,本想直接做个应用程序来说明问题,但苦于工作繁忙并考虑到以简单为主,故先对反射发送(reflection emit)的使用做一些介绍。文章最后再给出一个实例。
下面的程序在运行时生成了一个test.cs文件,并调用csc编译成test.dll文件,然后利用type.invokemember()方法调用其中的sayhello()方法,然后和原始方法对比一下性能。
using system;
using system.diagnostics;
using system.io;
using system.reflection;
namespace invokemember
{
/// <summary>
/// class1 的摘要说明。
/// </summary>
class class1 { /// <summary>
/// 应用程序的主入口点。
/// </summary>
[stathread]
static void main(string[] args)
{
//循环次数
const int iterations = 100;
//计算所用时间
datetime starttime = datetime.now;
for(int i = 0;i< iterations;i++) { //对照方法
console.writeline("hello,world");
}
timespan elasped = datetime.now – starttime;
console.writeline("looping elapsed milliseconds:" + elasped.totalmilliseconds + "for {0} iterations",iterations);
//使用反射发送
reflectiontest t = new reflectiontest();
//计算所用时间
starttime = datetime.now;
for(int i = 0;i < iterations;i++)
{
t.dooperation();
}
elasped = datetime.now – starttime;
console.writeline("looping elapsed milliseconds:" + elasped.totalmilliseconds + "for {0} iterations",iterations);
console.readline();
}
}
/// <summary>
/// reflection 的摘要说明。
/// </summary>
public class reflectiontest
{
//保存动态生成并编译的类的type对象
type thetype = null;
//保存动态生成类的实例
object theclass = null;
/// <summary>
/// 供client调用的方法
/// </summary>
public void dooperation()
{
//未初始化
if(thetype == null)
{
//初始化
generatecode();
}
//调用方法时的参数数组(此处为空)
object[] arguments = new object[0];
//调用动态生成类的方法
thetype.invokemember("sayhello",//要调用的方法名
bindingflags.default|bindingflags.invokemethod,//binding标志,具体参看msdn
null,//使用默认binding对象
theclass,//在theclass实例上调用此方法
arguments//调用方法时的参数数组
);
}
/// <summary>
/// 运行时生成代码
/// </summary>
private void generatecode()
{
//文件名
string filename = "test";
//打开文件,如果不存在,则创建
stream s = file.open(filename + ".cs",filemode.create);
//创建一个streamwriter来写入数据
streamwriter wrtr = new streamwriter(s);
//写入动态创建类的源代码
wrtr.writeline("// 动态创建test类");
//类名
string classname = "testclass";
wrtr.writeline("using system;");
wrtr.writeline("class {0}",classname);
wrtr.writeline("{");
wrtr.writeline("\tpublic void sayhello()");
wrtr.writeline("\t{");
wrtr.writeline("\t\tconsole.writeline(\"hello,world\");");
wrtr.writeline("\t}");
wrtr.writeline("}");
//关闭streamwriter和文件
wrtr.close();
s.close();
//启动进程编译源文件
//指定参数
processstartinfo psi = new processstartinfo();
//启动cmd.exe
psi.filename = "cmd.exe";
//cmd.exe的参数,/c-close,完成后关闭;后为参数,指定cmd.exe使用csc来编译刚才生成的源文件
string compilestring = "/c c:\\winnt\\microsoft.net\\framework\\v1.1.4322\\csc.exe /optimize+ /target:library {0}.cs";
psi.arguments = string.format(compilestring,filename);
//运行时的风格-最小化
psi.windowstyle = processwindowstyle.minimized;
//启动进程
process proc = process.start(psi);
//指定当前在此进程退出前等待
proc.waitforexit();
//从编译好的dll文件load一个assembly
assembly a = assembly.loadfrom(filename + ".dll");
//创建类的实例
theclass = a.createinstance(classname);
//取得此类实例的类型
thetype = a.gettype(classname);
//删除源文件
//file.delete(fliename + ".cs");
}
}
}
