<span style="font-size: 10pt">反射是.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);
<table height="18" cellspacing="0" cellpadding="0" width="470" border="0"><tr>
<td align="center"><span style="font-size: 10pt"></td>
</tr></table>
<span style="font-size: 10pt">//使用反射发送
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("ttConsole.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:WINNTMicrosoft.NETFrameworkv1.1.4322csc.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");
}
}}最后贴一个BindingFlags的Demo Share with EveryOne
using System;
using System.Reflection;
using System.IO;
namespace BindingFlagsSnippet
{
??? class EntryPoint
??? {
??????? static void Main(string[] args)
??????? {
??????????? Invoke.Go();
??????? }
??? }
???
??? class Invoke
??? {
??????? public static void Go()
??????? {
??????????? // BindingFlags.InvokeMethod
??????????? // Call a static method.
??????????? Type t = typeof (TestClass);
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking a static method.");
??????????? Console.WriteLine("-------------------------");
??????????? t.InvokeMember ("SayHello",BindingFlags.InvokeMethod,null,new object [] {});
??????????? // BindingFlags.InvokeMethod
??????????? // Call an instance method.
??????????? TestClass c = new TestClass ();
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking an instance method.");
??????????? Console.WriteLine("----------------------------");
??????????? c.GetType().InvokeMember ("AddUp",c,new object [] {});
??????????? c.GetType().InvokeMember ("AddUp",new object [] {});
???????????
??????????? // BindingFlags.InvokeMethod
??????????? // Call a method with parameters.
??????????? object [] args = new object [] {100.09,184.45};
??????????? object result;
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking a method with parameters.");
??????????? Console.WriteLine("---------------------------------");
??????????? result = t.InvokeMember ("ComputeSum",args);
??????????? Console.WriteLine ("{0} + {1} = {2}",args[0],args[1],result);
??????????? // BindingFlags.GetField,SetField
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking a field (getting and setting.)");
??????????? Console.WriteLine("--------------------------------------");
??????????? // Get a field value.
??????????? result = t.InvokeMember ("Name",BindingFlags.GetField,new object [] {});
??????????? Console.WriteLine ("Name == {0}",result);
??????????? // Set a field.
??????????? t.InvokeMember ("Name",BindingFlags.SetField,new object [] {"NewName"});
??????????? result = t.InvokeMember ("Name",result);
???????????
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking an indexed property (getting and setting.)");
??????????? Console.WriteLine("--------------------------------------------------");
??????????? // BindingFlags.GetProperty
??????????? // Get an indexed property value.
??????????? int? index = 3;
??????????? result = t.InvokeMember ("Item",BindingFlags.GetProperty,new object [] {index});
??????????? Console.WriteLine ("Item[{0}] == {1}",index,result);
??????????? // BindingFlags.SetProperty
??????????? // Set an indexed property value.
??????????? index = 3;
??????????? t.InvokeMember ("Item",BindingFlags.SetProperty,new object [] {index,"NewValue"});
??????????? result = t.InvokeMember ("Item",result);
???????????
??????????? Console.WriteLine();
??????????? Console.WriteLine("Getting a field or property.");
??????????? Console.WriteLine("----------------------------");
??????????? // BindingFlags.GetField
??????????? // Get a field or property.
??????????? result = t.InvokeMember ("Name",BindingFlags.GetField | BindingFlags.GetProperty,result);
??????????? // BindingFlags.GetProperty
??????????? result = t.InvokeMember ("Value",new object [] {});
??????????? Console.WriteLine ("Value == {0}",result);
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking a method with named parameters.");
??????????? Console.WriteLine("---------------------------------------");
??????????? // BindingFlags.InvokeMethod
??????????? // Call a method using named parameters.
??????????? object[] argValues = new object [] {"Mouse","Micky"};
??????????? String [] argNames = new String [] {"lastName","firstName"};
??????????? t.InvokeMember ("PrintName",argValues,argNames);
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking a default member of a type.");
??????????? Console.WriteLine("------------------------------------");
??????????? // BindingFlags.Default
??????????? // Call the default member of a type.
??????????? Type t3 = typeof (TestClass2);
??????????? t3.InvokeMember ("",BindingFlags.InvokeMethod | BindingFlags.Default,new TestClass2(),new object [] {});
?
??????????? // BindingFlags.Static,NonPublic,and Public
??????????? // Invoking a member by reference.
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking a method by reference.");
??????????? Console.WriteLine("-------------------------------");
??????????? MethodInfo m = t.GetMethod("Swap");
??????????? args = new object[2];
??????????? args[0] = 1;
??????????? args[1] = 2;
??????????? m.Invoke(new TestClass(),args);
??????????? Console.WriteLine ("{0},{1}",args[1]);
??????????? // The string is case-sensitive.
??????????? Type type = Type.GetType("System.String");
??????????? // Check to see if the value is valid. If the object is null,the type does not exist.
??????????? if (type == null)
??????????? {
??????????????? Console.WriteLine("Please ensure that you specify only valid types in the type field.");
??????????????? Console.WriteLine("The type name is case-sensitive.");
??????????????? return;
??????????? }
??????????? // Declare and populate the arrays to hold the information.
??????????? // You must declare either NonPublic or Public with Static or the search will not work.
??????????? FieldInfo [] fi = type.GetFields (BindingFlags.Static |
??????????????? BindingFlags.NonPublic | BindingFlags.Public);?
??????????? // BindingFlags.NonPublic
??????????? MethodInfo [] miNonPublic = type.GetMethods (BindingFlags.Static |
??????????????? BindingFlags.NonPublic);
??????????? // BindingFlags.Public
??????????? MethodInfo [] miPublic = type.GetMethods (BindingFlags.Static |
??????????????? BindingFlags.Public);
??????????? // Iterate through all the nonpublic methods.
??????????? foreach (MethodInfo method in miNonPublic)
??????????? {
??????????????? Console.WriteLine(method);
??????????? }
??????????? // Iterate through all the public methods.
??????????? foreach (MethodInfo method in miPublic)
??????????? {
??????????????? Console.WriteLine(method);
??????????? }
??????????? // Iterate through all the fields.
??????????? foreach (FieldInfo f in fi)
??????????? {
??????????????? Console.WriteLine(f);
??????????? }
??????????? // BindingFlags.Instance
??????????? // Call an instance method.
??????????? TestClass tc = new TestClass ();
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking an Instance method.");
??????????? Console.WriteLine("----------------------------");
??????????? tc.GetType().InvokeMember ("AddUp",BindingFlags.Public |
??????????????? BindingFlags.Instance | BindingFlags.CreateInstance,
??????????????? null,tc,new object [] {});
??????????? // BindingFlags.CreateInstance
??????????? // Calling and creating an instance method.
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking and creating an instance method.");
??????????? Console.WriteLine("-----------------------------------------");
??????????? tc.GetType().InvokeMember ("AddUp",new object [] {});
??????????? // BindingFlags.DeclaredOnly
??????????? TestClass tc2 = new TestClass();
??????????? Console.WriteLine();
??????????? Console.WriteLine("DeclaredOnly members");
??????????? Console.WriteLine("---------------------------------");
??????????? System.Reflection.MemberInfo[] memInfo =
??????????????? tc2.GetType().GetMembers(BindingFlags.DeclaredOnly);
??????????? for(int i=0;i
??????????? // BindingFlags.SuppressChangeType
??????????? TestClass obj = new TestClass();
??????????? Console.WriteLine();
??????????? Console.WriteLine("Invoking static method - PrintName");
??????????? Console.WriteLine("---------------------------------");
??????????? System.Reflection.MethodInfo methInfo =
??????????????? obj.GetType().GetMethod("PrintName");
??????????? methInfo.Invoke(obj,BindingFlags.SuppressChangeType |
??????????????? BindingFlags.InvokeMethod,new object[]
??????????????? {"Brad","Smith"},null);
??????????? // BindingFlags.IgnoreCase
??????????? Console.WriteLine();
??????????? Console.WriteLine("Using IgnoreCase and invoking the PrintName method.");
??????????? Console.WriteLine("---------------------------------------------------");
??????????? methInfo = obj.GetType().GetMethod("PrintName");
??????????? methInfo.Invoke(obj,BindingFlags.IgnoreCase |
??????????????? BindingFlags.InvokeMethod,new object[]
??????????????? {"brad","smith"},null);
??????????? // BindingFlags.IgnoreReturn
??????????? Console.WriteLine();
??????????? Console.WriteLine("Using IgnoreReturn and invoking the PrintName method.");
??????????? Console.WriteLine("-----------------------------------------------------");
??????????? methInfo = obj.GetType().GetMethod("PrintName");
??????????? methInfo.Invoke(obj,BindingFlags.IgnoreReturn |
??????????????? BindingFlags.InvokeMethod,null);
??????????? // BindingFlags.OptionalParamBinding
??????????? Console.WriteLine();
??????????? Console.WriteLine("Using OptionalParamBinding and invoking the PrintName method.");
??????????? Console.WriteLine("-------------------------------------------------------------");
??????????? methInfo = obj.GetType().GetMethod("PrintName");
??????????? methInfo.Invoke(obj,BindingFlags.OptionalParamBinding |
??????????????? BindingFlags.InvokeMethod,null);
??????????? // BindingFlags.ExactBinding
??????????? Console.WriteLine();
??????????? Console.WriteLine("Using ExactBinding and invoking the PrintName method.");
??????????? Console.WriteLine("-----------------------------------------------------");
??????????? methInfo = obj.GetType().GetMethod("PrintName");
??????????? methInfo.Invoke(obj,BindingFlags.ExactBinding |
??????????????? BindingFlags.InvokeMethod,null);
?
??????????? // BindingFlags.FlattenHierarchy
??????????? Console.WriteLine();
??????????? Console.WriteLine("Using FlattenHierarchy and invoking the PrintName method.");
??????????? Console.WriteLine("---------------------------------------------------------");
??????????? methInfo = obj.GetType().GetMethod("PrintName");
??????????? methInfo.Invoke(obj,BindingFlags.FlattenHierarchy |
??????????????? BindingFlags.InvokeMethod,null);
??????? }
??? }
??? public class TestClass
??? {
??????? public String Name;
??????? private Object [] values = new Object [] {0,1,2,3,4,5,6,7,8,9};
??????? public Object this [int index]
??????? {
??????????? get
??????????? {
??????????????? return values[index];
??????????? }
??????????? set
??????????? {
??????????????? values[index] = value;
??????????? }
??????? }
??????? public Object Value
??????? {
??????????? get
??????????? {
??????????????? return "the value";
??????????? }
??????? }
??????? public TestClass ()
??????? {
??????????? Name = "initialName";
??????? }
??????? int methodCalled = 0;
??????? public static void SayHello ()
??????? {
??????????? Console.WriteLine ("Hello");
??????? }
??????? public void AddUp ()
??????? {
??????????? methodCalled++;
??????????? Console.WriteLine ("AddUp Called {0} times",methodCalled);
??????? }
??????? public static double ComputeSum (double d1,double d2)
??????? {
??????????? return d1 + d2;
??????? }
??????? public static void PrintName (String firstName,String lastName)
??????? {
??????????? Console.WriteLine ("{0},lastName,firstName);
??????? }
??????? public void PrintTime ()
??????? {
??????????? Console.WriteLine (DateTime.Now);
??????? }
??????? public void Swap(ref int a,ref int b)
??????? {
??????????? int x = a;
??????????? a = b;
??????????? b = x;
??????? }
??? }
??? [DefaultMemberAttribute ("PrintTime")]
??? public class TestClass2
??? {
??????? public void PrintTime ()
??????? {
??????????? Console.WriteLine (DateTime.Now);
??????? }
??? }
}
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|