《C利用反射动态编译代码创建类的实例并调用其成员》由会员分享,可在线阅读,更多相关《C利用反射动态编译代码创建类的实例并调用其成员(7页珍藏版)》请在金锄头文库上搜索。
1、【经典实例】利用C#反射动态编译代码,创建类的实例,并调用其成员收藏关键是以下内容有一些需要学习的地方。GenerateCode()函数动态生成编译代码,还有动态调用类的函数名。C#反射是.net中的高级功能之一,利用反射可以实现许多以前看来匪夷所思的功能,下面是我看了Programming(OReilly)之后对于反射的一点实践,本想直接做个应用程序来说明问题,但苦于工作繁忙并考虑到以简单为主,故先对反射发送(reflectionemit)的使用做一些介绍。文章最后再给出一个实例。方法下面的程序在运行时生成了一个Test.cs文件,并调用esc编译成Test.dll文件,然后利用Typenv
2、okeMember()调用其中的SayHello()方法,然后和原始方法对比一下性能。usingSystem;usingSystem.Diagnostics;usingSystem.IO;usingSystem.Reflection;namespaceInvokeMember/Class1的摘要说明。/classClass1/应用程序的主入口点。/STAThreadstaticvoidMain(stringargs)/循环次数constintiterations=100;/计算所用时间DateTimestartTime=DateTime.Now;for(inti=0;iiterations;i
3、+)/对照方法Console.WriteLine(Hello,World);TimeSpanelasped=DateTime.Now-startTime;0Console.WriteLine(LoopingElapsedmilliseconds:+elasped.TotalMilliseconds+foriterations,iterations);/使用反射发送ReflectionTestt=newReflectionTest();/计算所用时间startTime=DateTime.Now;for(inti=0;iiterations;i+)t.DoOperation();0elasped=
4、DateTime.Now-startTime;Console.WriteLine(LoopingElapsedmilliseconds:+elasped.TotalMilliseconds+foriterations,iterations);Console.ReadLine();/Reflection的摘要说明。/publicclassReflectionTest/保存动态生成并编译的类的type对象TypetheType=null;/保存动态生成类的实例objecttheClass=null;/供Client调用的方法/publicvoidDoOperation()/未初始化if(theTy
5、pe=null)/初始化GenerateCode();/调用方法时的参数数组(此处为空)objectarguments=newobject0;/调用动态生成类的方法theType.InvokeMember(SayHello,/要调用的方法名BindingFlags.Default|BindingFlags.InvokeMethod,/Binding标志,具体参看msdnnull,/使用默认Binding对象theClass,/在theClass实例上调用此方法arguments调用方法时的参数数组);/运行时生成代码/privatevoidGenerateCode()/文件名stringfil
6、eName=Test;/打开文件,如果不存在,则创建Streams=File.Open(fileName+.cs,FileMode.Create);/创建一个StreamWriter来写入数据StreamWriterwrtr=newStreamWriter(s);/写入动态创建类的源代码wrtr.WriteLine(/动态创建Test类);/类名stringclassName=TestClass;wrtr.WriteLine(usingSystem;);wrtr.WriteLine(class0,className);wrtr.WriteLine();wrtr.WriteLine(tpubli
7、cvoidSayHello();wrtr.WriteLine(t);wrtr.WriteLine(ttConsole.WriteLine(Hello,World););wrtr.WriteLine(t);wrtr.WriteLine();/关闭StreamWriter和文件wrtr.Close();s.Close();/启动进程编译源文件/指定参数ProcessStartInfopsi=newProcessStartInfo();/启动cmd.exepsi.FileName=cmd.exe;/cmd.exe的参数,/cclose,完成后关闭;后为参数,指定cmd.exe使用esc来编译刚才生成
8、的源文件stringcompileString=/cC:WINNTMicrosoft.NETFrameworkv1.1.4322csc.exe/optimize+/target:library0.cs;psi.Arguments=String.Format(compileString,fileName);/运行时的风格最小化psi.WindowStyle=ProcessWindowStyle.Minimized;/启动进程Processproc=Process.Start(psi);/指定当前在此进程退出前等待proc.WaitForExit();/从编译好的dll文件load一个Assemb
9、lyAssemblya=Assembly.LoadFrom(fileName+.dll);/创建类的实例theClass=a.CreateInstance(className);/取得此类实例的类型theType=a.GetType(className);/删除源文件/File.Delete(flieName+.cs);usingSystem;usingSystem.Diagnostics;usingSystem.IO;usingSystem.Reflection;namespaceInvokeMember/Class1的摘要说明。/classClass1/应用程序的主入口点。/STAThre
10、adstaticvoidMain(stringargs)/循环次数constintiterations=100;/计算所用时间DateTimestartTime=DateTime.Now;for(inti=0;iiterations;i+)/对照方法Console.WriteLine(Hello,World);TimeSpanelasped=DateTime.Now-startTime;0Console.WriteLine(LoopingElapsedmilliseconds:+elasped.TotalMilliseconds+foriterations,iterations);/使用反射发
11、送ReflectionTestt=newReflectionTest();/计算所用时间startTime=DateTime.Now;for(inti=0;iiterations;i+)t.DoOperation();elasped=DateTime.Now-startTime;0Console.WriteLine(LoopingElapsedmilliseconds:+elasped.TotalMilliseconds+foriterations,iterations);Console.ReadLine();/Reflection的摘要说明。/publicclassReflectionTes
12、t/保存动态生成并编译的类的type对象TypetheType=null;/保存动态生成类的实例objecttheClass=null;/供Client调用的方法/publicvoidDoOperation()/未初始化if(theType=null)/初始化GenerateCode();/调用方法时的参数数组(此处为空)objectarguments=newobject0;/调用动态生成类的方法theType.InvokeMember(SayHello,/要调用的方法名BindingFlags.Default|BindingFlags.InvokeMethod,/Binding标志,具体参看
13、msdnnull,/使用默认Binding对象theClass,/在theClass实例上调用此方法arguments调用方法时的参数数组);/运行时生成代码/privatevoidGenerateCode()/文件名stringfileName=Test;/打开文件,如果不存在,则创建Streams=File.Open(fileName+.cs,FileMode.Create);/创建一个StreamWriter来写入数据StreamWriterwrtr=newStreamWriter(s);/写入动态创建类的源代码wrtr.WriteLine(/动态创建Test类);/类名stringcl
14、assName=TestClass;wrtr.WriteLine(usingSystem;);wrtr.WriteLine(class0,className);wrtr.WriteLine();wrtr.WriteLine(tpublicvoidSayHello();wrtr.WriteLine(t);wrtr.WriteLine(ttConsole.WriteLine(Hello,World););wrtr.WriteLine(t);wrtr.WriteLine();/关闭StreamWriter和文件wrtr.Close();s.Close();/启动进程编译源文件/指定参数ProcessStartInfopsi=newProcessStartInfo();/启动cmd.exepsi.Fil