在CLR VIA 的Demo中看到关于反射性能的几个例子,演示了反射操作实例及性能表现。反射的过程其实就是根据要查找的反射信息(字段名,方法名,类名等),在元数据中逐字符匹配的查找字段名,类型名等,然后定位到IL代码编译执行(所以会有大小写区分)。由于元数据是记录了程序集所有类型以及成员的描述信息,所以在其中查找指定的信息是件浪费性能的事情。如何快速匹配到对应的元数据信息,然后定位到IL执行代码去执行,这是本身反射性能提升的直接途径,当然这个过程已经很难优化,但是可以通过缓存管理首次的结果提高效率。类似JIT对IL方法指令的编译,首次编译后保存CLR 元数据相关的结构表中,再下一次执行时直接上次编译的CPU指令。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Dynamic; namespace Demo { class Program { static void Main(string[] args) { Type t = typeof(SomeType); //方法一 InvokeMember Invoker.UseInvokeMemberToBindAndInvokeTheMember(t); //方法二 MemberInfo派生类 SetValue->GetSetValueMethod->调用SetValueMethod Invoker.BindToMemberThenInvokeTheMember(t); //方法三 委托操作 看IL的调用栈要比上个浅,因为直接查找了GetMethod,但没有缓存仍然每次都要查找 Invoker.BindToMemberCreateDelegateToMemberThenInvokeTheMember(t); //方法四 Dynamic动态(4.0特性),dynamic经过语法糖编译为IL时对实现了类似方法三的效果, //但是利用了CallSite的委托缓存容器,一次查找重复利用 Invoker.UseDynamicToBindAndInvokeTheMember(t); Console.ReadLine(); } } ////// 要反射的类型DEMO /// public sealed class SomeType { private Int32 m_someField; public SomeType(ref Int32 x) { x *= 2; } public override String ToString() { return m_someField.ToString(); } public Int32 SomeProp { get { return m_someField; } set { m_someField = value; } } public event EventHandler SomeEvent; private void NoCompilerWarnings() { SomeEvent.ToString(); } } public static class Invoker { ////// 过滤成员标志 /// private const BindingFlags c_bf = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; ////// 通过类型的InvokeMember实例的反射成员操作 (最差,次次反射对象) /// /// public static void UseInvokeMemberToBindAndInvokeTheMember(Type t) { // Construct an instance of the Type Object[] args = new Object[] { 12 }; // Constructor arguments Object obj = t.InvokeMember(null, c_bf | BindingFlags.CreateInstance, null, null, args); // Read and write to a field t.InvokeMember("m_someField", c_bf | BindingFlags.SetField, null, obj, new Object[] { 5 }); Int32 v = (Int32)t.InvokeMember("m_someField", c_bf | BindingFlags.GetField, null, obj, null); // Call a method String s = (String)t.InvokeMember("ToString", c_bf | BindingFlags.InvokeMethod, null, obj, null); // Read and write a property try { t.InvokeMember("SomeProp", c_bf | BindingFlags.SetProperty, null, obj, new Object[] { 0 }); } catch (TargetInvocationException e) { } t.InvokeMember("SomeProp", c_bf | BindingFlags.SetProperty, null, obj, new Object[] { 2 }); v = (Int32)t.InvokeMember("SomeProp", c_bf | BindingFlags.GetProperty, null, obj, null); // Add and remove a delegate from the event by invoking the event抯 add/remove methods EventHandler eh = new EventHandler(EventCallback); t.InvokeMember("add_SomeEvent", c_bf | BindingFlags.InvokeMethod, null, obj, new Object[] { eh }); t.InvokeMember("remove_SomeEvent", c_bf | BindingFlags.InvokeMethod, null, obj, new Object[] { eh }); } ////// 通过获取构造实例,获取成员反射类型设置(反射一次对象,效率高于上个) /// MemberInfo派生类 SetValue->GetSetValueMethod->调用SetValueMethod /// /// public static void BindToMemberThenInvokeTheMember(Type t) { // Construct an instance // ConstructorInfo ctor = t.GetConstructor(new Type[] { Type.GetType("System.Int32&") }); ConstructorInfo ctor = t.GetConstructor(new Type[] { typeof(Int32).MakeByRefType() }); Object[] args = new Object[] { 12 }; // Constructor arguments Object obj = ctor.Invoke(args); // Read and write to a field FieldInfo fi = obj.GetType().GetField("m_someField", c_bf); fi.SetValue(obj, 33); // Call a method MethodInfo mi = obj.GetType().GetMethod("ToString", c_bf); String s = (String)mi.Invoke(obj, null); // Read and write a property PropertyInfo pi = obj.GetType().GetProperty("SomeProp", typeof(Int32)); try { pi.SetValue(obj, 0, null); } catch (TargetInvocationException e) { } pi.SetValue(obj, 2, null); // Add and remove a delegate from the event EventInfo ei = obj.GetType().GetEvent("SomeEvent", c_bf); EventHandler eh = new EventHandler(EventCallback); // See ei.EventHandlerType ei.AddEventHandler(obj, eh); ei.RemoveEventHandler(obj, eh); } ////// 通过委托执行实例成员的IL方法(效率高于上个,比较适合批量处理大量未知对象的序列化) /// /// public static void BindToMemberCreateDelegateToMemberThenInvokeTheMember(Type t) { // Construct an instance (You can't create a delegate to a constructor) Object[] args = new Object[] { 12 }; // Constructor arguments Object obj = Activator.CreateInstance(t, args); // NOTE: You can't create a delegate to a field // Call a method MethodInfo mi = obj.GetType().GetMethod("ToString", c_bf); var toString = (Func)Delegate.CreateDelegate(typeof(Func ), obj, mi); String s = toString(); // Read and write a property PropertyInfo pi = obj.GetType().GetProperty("SomeProp", typeof(Int32)); var setSomeProp = (Action )Delegate.CreateDelegate(typeof(Action ), obj, pi.GetSetMethod()); try { setSomeProp(0); } catch (ArgumentOutOfRangeException) { } setSomeProp(2); var getSomeProp = (Func )Delegate.CreateDelegate(typeof(Func ), obj, pi.GetGetMethod()); // Add and remove a delegate from the event EventInfo ei = obj.GetType().GetEvent("SomeEvent", c_bf); var addSomeEvent = (Action )Delegate.CreateDelegate(typeof(Action ), obj, ei.GetAddMethod()); addSomeEvent(EventCallback); var removeSomeEvent = (Action )Delegate.CreateDelegate(typeof(Action ), obj, ei.GetRemoveMethod()); removeSomeEvent(EventCallback); } /// /// 动态代理方式UseDynamic,但是利用了CallSite的委托缓存容器,性能要高于方法三 /// /// public static void UseDynamicToBindAndInvokeTheMember(Type t) { // Construct an instance (You can't create a delegate to a constructor) Object[] args = new Object[] { 12 }; // Constructor arguments dynamic obj = Activator.CreateInstance(t, args); // Read and write a property try { obj.SomeProp = 0; } catch (ArgumentOutOfRangeException ex) { throw ex; } obj.SomeProp = 2; Int32 val = (Int32)obj.SomeProp; // Add and remove a delegate from the event obj.SomeEvent += new EventHandler(EventCallback); obj.SomeEvent -= new EventHandler(EventCallback); } // Callback method added to the event private static void EventCallback(Object sender, EventArgs e) { } } }