日期:2008-04-22  浏览次数:20618 次

反射是.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(\"Hel