反射发送实战(-)InvokeMember

反射是.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

性能上不占优势,主要是因为要进行写文件和编译的工作,但是后面的方法会对性能进行优化,到最后一个方法时性能会有大幅提高,但是最后一种方法的实用性不如前两种。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值