【经典实例】利用C#反射动态编译代码,创建类的实例,并调用其成员
2010-01-16 01:26
1241 查看
关键是以下内容有一些需要学习的地方。GenerateCode()函数动态生成编译代码,还有动态调用类的函数名。
反射是.net中的高级功能之一,利用反射可以实现许多以前看来匪夷所思的功能,下面是我看了《Programming C#》(O'Reilly)之后对于反射的一点实践,本想直接做个应用程序来说明问题,但苦于工作繁忙并考虑到以简单为主,故先对反射发送(reflection emit)的使用做一些介绍。文章最后再给出一个实例。
下面的程序在运行时生成了一个Test.cs文件,并调用csc编译成Test.dll文件,然后利用Type.InvokeMember()方法调用其中的SayHello()方法,然后和原始方法对比一下性能。
程序运行结果:
Hello,World
Hello,World
Looping Elapsed milliseconds:93.75 for 100 iterations
Hello,World
Hello,World
Looping Elapsed milliseconds:2875 for 100 iterations
性能上不占优势,主要是因为要进行写文件和编译的工作,但是后面的方法会对性能进行优化,到最后一个方法时性能会有大幅提高,但是最后一种方法的实用性不如前两种。
反射是.net中的高级功能之一,利用反射可以实现许多以前看来匪夷所思的功能,下面是我看了《Programming C#》(O'Reilly)之后对于反射的一点实践,本想直接做个应用程序来说明问题,但苦于工作繁忙并考虑到以简单为主,故先对反射发送(reflection emit)的使用做一些介绍。文章最后再给出一个实例。
下面的程序在运行时生成了一个Test.cs文件,并调用csc编译成Test.dll文件,然后利用Type.InvokeMember()方法调用其中的SayHello()方法,然后和原始方法对比一下性能。
using System; using System.Diagnostics; using System.IO; using System.Reflection; namespace InvokeMember { /// /// Class1 的摘要说明。 /// class Class1 { /// /// 应用程序的主入口点。 /// [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(); } } /// /// Reflection 的摘要说明。 /// public class ReflectionTest { //保存动态生成并编译的类的type对象 Type theType = null; //保存动态生成类的实例 object theClass = null; /// /// 供Client调用的方法 /// 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//调用方法时的参数数组 ); } /// /// 运行时生成代码 /// 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"); } } }
程序运行结果:
Hello,World
Hello,World
Looping Elapsed milliseconds:93.75 for 100 iterations
Hello,World
Hello,World
Looping Elapsed milliseconds:2875 for 100 iterations
性能上不占优势,主要是因为要进行写文件和编译的工作,但是后面的方法会对性能进行优化,到最后一个方法时性能会有大幅提高,但是最后一种方法的实用性不如前两种。
相关文章推荐
- c# 利用反射 从json字符串 动态创建类的实例 并动态为实例成员赋值
- C#用反射将Model类动态载入表单 利用Velocity传值 调用只需一句代码
- 利用反射来动态创建实例和调用方法
- 利用反射动态创建实例并调用方法
- 利用反射来动态创建实例和调用方法
- [c#美味] 使用反射动态创建实例并调用方法
- 利用反射来动态创建实例和调用方法
- 利用反射来动态创建实例和调用方法
- 利用反射来动态创建实例和调用方法
- 利用反射来动态创建实例和调用方法
- 利用反射来动态创建实例和调用方法(上)
- (C#)利用反射动态调用类成员[转载]
- C#动态执行字符串(动态创建代码)的实例代码
- 利用反射动态调用组件或类成员
- 详解C# 利用反射根据类名创建类的实例对象
- (C#)利用反射动态调用类成员
- C# 利用反射动态创建对象——带参数的构造函数和String类型
- 利用C#的反射机制动态调用DLL类库
- 使用反射技术动态创建类对象(实例代码)
- (C#)利用反射动态调用类成员