现在的位置: 首页 > 综合 > 正文

CLR VIA反射性能比较的例子

2011年03月25日 ⁄ 综合 ⁄ 共 5659字 ⁄ 字号 评论关闭

在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();
}
}

///<summary>
/// 要反射的类型DEMO
///</summary>
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
{
///<summary>
/// 过滤成员标志
///</summary>
private const BindingFlags c_bf = BindingFlags.DeclaredOnly | BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance;


///<summary>
/// 通过类型的InvokeMember实例的反射成员操作 (最差,次次反射对象)
///</summary>
///<param name="t"></param>
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 });
}

///<summary>
/// 通过获取构造实例,获取成员反射类型设置(反射一次对象,效率高于上个)
/// MemberInfo派生类 SetValue->GetSetValueMethod->调用SetValueMethod
///</summary>
///<param name="t"></param>
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);
}

///<summary>
/// 通过委托执行实例成员的IL方法(效率高于上个,比较适合批量处理大量未知对象的序列化)
///</summary>
///<param name="t"></param>
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<String>)Delegate.CreateDelegate(typeof(Func<String>), obj, mi);
String s = toString();

// Read and write a property
PropertyInfo pi = obj.GetType().GetProperty("SomeProp", typeof(Int32));
var setSomeProp = (Action<Int32>)Delegate.CreateDelegate(typeof(Action<Int32>), obj, pi.GetSetMethod());
try
{
setSomeProp(0);
}
catch (ArgumentOutOfRangeException)
{

}
setSomeProp(2);
var getSomeProp = (Func<Int32>)Delegate.CreateDelegate(typeof(Func<Int32>), obj, pi.GetGetMethod());


// Add and remove a delegate from the event
EventInfo ei = obj.GetType().GetEvent("SomeEvent", c_bf);
var addSomeEvent = (Action<EventHandler>)Delegate.CreateDelegate(typeof(Action<EventHandler>), obj, ei.GetAddMethod());
addSomeEvent(EventCallback);
var removeSomeEvent = (Action<EventHandler>)Delegate.CreateDelegate(typeof(Action<EventHandler>), obj, ei.GetRemoveMethod());
removeSomeEvent(EventCallback);
}

///<summary>
/// 动态代理方式UseDynamic,但是利用了CallSite的委托缓存容器,性能要高于方法三
///</summary>
///<param name="t"></param>
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) { }
}
}

 

抱歉!评论已关闭.