反射是.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
{
    /// <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");
        }
    }
}

(转)反射发送实战(-)InvokeMember的更多相关文章

  1. scrapy——4 —反爬措施—logging—重要参数—POST请求发送实战

    scrapy——4 常用的反爬虫策略有哪些 怎样使用logging设置 Resquest/Response重要参数有哪些 Scrapy怎么发送POST请求 动态的设置User-Agent(随即切换Us ...

  2. Windows下底层数据包发送实战

    1.简介 所谓“底层数据包”指的是在“运行”于数据链路层的数据包,简单的说就是“以太网帧”,而我们常用的Socket只能发送“运行”在传输层的TCP.UDP等包,这些传输层数据包已经能满足绝大部分需求 ...

  3. Java反射机制实战——字段篇

    首先,我们来认识几个类. Class(java.lang.Class) Class对象是一个特殊对象,每一个类都有一个Class对象,用来创建该类的“常规”对象.可以通过对象的getClass()方法 ...

  4. 实战Java的反射机制

    众所周知,Java要调用某个对象的方法首先需要对象实例化后才能调用. 而实例化对象常见的就是new执行和spring(DI)的依赖注入了. Spring的DI其实就是以反射作为最基础的技术手段. 一. ...

  5. C#基础系列 - 反射基础

    反射用于在程序运行过程中,获取类里面的信息或发现程序集并运行的一个过程.通过反射可以获得.dll和.exe后缀的程序集里面的信息.使用反射可以看到一个程序集内部的类,接口,字段,属性,方法,特性等信息 ...

  6. Kotlin反射实践操作详解

    继续对反射进行实战. 获取构造方法: 先定义一个主构造方法,2个次构造方法,接下来咱们用反射来获取一下构造方法: 其结果: [fun <init>(kotlin.Int, kotlin.S ...

  7. Java高级篇反射和注解

    反射是什么? 反射的作用?能带来什么好处? 反射的使用? 注解的使用? 注解和反射配合实战...

  8. C#程序实现动态调用DLL的研究(转)

    摘 要:在<csdn开发高手>2004年第03期中的<化功大法——将DLL嵌入EXE>一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在可执行文件运行时,自动从资 ...

  9. C#程序实现动态调用DLL的研究[转]

    摘   要: 在< csdn 开发高手> 2004 年第 03 期中的<化功大法——将 DLL 嵌入 EXE >一文,介绍了如何把一个动态链接库作为一个资源嵌入到可执行文件,在 ...

随机推荐

  1. sql查询每门课程成绩最高的学生

    给出数据库(sco)如下图: 查出每门课程成绩最高的学生 select b.id,b.kemu,b.name,b.chengji from (select kemu,max(chengji) maxc ...

  2. uva 10077 - The Stern-Brocot Number System

    想法: 初始化三個數L=0/1, M=1/1, R=1/0,設輸入的分數為a: 如果a<M,那麼要往左邊走,    R = M;    M = (L分子+M分子)/(L分母+M分母); 如果a& ...

  3. redis php

    redis php 学习1.连接$redis = new redis();$result = $redis->connect('127.0.0.1',6379); 2.set$redis = n ...

  4. Html中input标签的使用

    1.取消按钮按下时的虚线框 在input里添加属性值 hideFocus 或者 HideFocus=true 2.只读文本框内容 在input里添加属性值 readonly 3.防止退后清空的TEXT ...

  5. [转] c#多线程(UI线程,控件显示更新) Invoke和BeginInvoke 区别

    如果只是直接使用子线程访问UI控件,直接看内容三,如果想深入了解从内容一看起. 一.Control.Invoke和BeginInvoke方法的区别 先上总结: Control.Invoke 方法 (D ...

  6. mysql优化 - mysql 的 hint

    FORCE INDEX 强制索引 只使用建立在field1上的索引,而不使用其它字段上的索引. SELECT * FROM table1 FORCE INDEX (field1) IGNORE IND ...

  7. Android中的一些小知识

    android中开发常用快捷键alt+/ 自动补全ctrl+1 有问题提示生成接收的参数 ctrl+L 在按2 注释// 注释 ctrl+//**/ 多行注释 ctrl+shift+/ android ...

  8. 11g v$session定位客户端IP

    11g v$session 新增PORT 字段 用于描述客户端的端口号 客户机从10.5.129.180 访问10.5.128.28 [oracle@cpool ~]$ netstat -na | g ...

  9. System.Drawing.Image.Save(Savepath),保存为jpg格式,参数错误,文件0kb解决办法

    问题场景:asp.net给图片添加文字水印保存为jpg格式时出现标题所描述错误(图片为.jpg格式): 简单验证:用本机的画图程序打开,然后保存为jpg格式会出现警告框"画图程序不能存储该文 ...

  10. JavaScript方法undefined/null原因探究及闭包简单实现

    昨天一个刚写前端不久的同学发消息问这个问题(如下图): HTML代码为(省略部分代码): <head> <script src="test.js">< ...