日期:2014-05-20 浏览次数:21214 次
public class FastProperty<T>
{
public delegate void SetValueDelegateHandler(T owner, object value);
private readonly Type ParameterType = typeof(object);
private T _owner;
public T Owner { get { return this._owner; } }
private Type _ownerType;
public FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
}
public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{
// 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
var callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
var para = callMethod.GetParameters()[0];
// 创建动态函数
DynamicMethod method = new DynamicMethod("EmitCallable", null, new Type[] { this._ownerType, ParameterType }, this._ownerType.Module);
// 获取动态函数的 IL 生成器
var il = method.GetILGenerator();
// 创建一个本地变量,主要用于 Object Type to Propety Type
var local = il.DeclareLocal(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}
http://www.cnblogs.com/mrlen/archive/2010/06/10/1755357.html
class T { private object P { get; set; } }
//得到私有属性
System.Reflection.PropertyInfo p = typeof(T).GetProperty("P", ystem.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//创建get,set委托
T t = new T();
Func<object> PGet = Delegate.CreateDelegate(typeof(Func<object>), t, p.GetGetMethod(true)) as Func<object>;
Action<object> PSet = Delegate.CreateDelegate(typeof(Action<object>), t, p.GetSetMethod(true)) as Action<object>;
//访问属性
PSet(new object());
object o = PGet();
------解决方案--------------------
多谢gomoku和guoyichao的指点。
如gomoku所说,那样测试的确有点不合适。
多谢guoyichao的提醒,这样的确很快。
重新修改了测试例子:
using System;
using System.Reflection;
using System.Reflection.Emit;
class Program
{
static void Main(string[] args)
{
//声明自定义类型,实例化
TestClass obj = new TestClass();
//调用静态方法设置值
FastProperty<TestClass> fp = new FastProperty<TestClass>(obj);
FastPropertyBufferd<TestClass> fp2 = new FastPropertyBufferd<TestClass>(obj, "Value");
int tick = Environment.TickCount;
FastProperty<TestClass>.SetValueDelegateHandler setter = fp.SetPropertyValue("Value", 5000);
for (int i = 0; i < 1000000; i++)
{
setter.Invoke(obj, 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastProperty".PadRight(20) + " : " + tick.ToString());
tick = Environment.TickCount;
for (int i = 0; i < 1000000; i++)
{
fp2.SetValue(5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("FastPropertyBufferd".PadRight(20) + " : " + tick);
tick = Environment.TickCount;
for (int i = 0; i < 1000000; i++)
{
SetNonePublicPropertyValue(obj, "Value", 5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("Direct reflect".PadRight(20) + " : " + tick);
tick = Environment.TickCount;
SetValueHandler del = Delegate.CreateDelegate(typeof(SetValueHandler),obj, "set_Value") as SetValueHandler;
for (int i = 0; i < 1000000; i++)
{
del(5000);
}
tick = Environment.TickCount - tick;
Console.WriteLine("CreateDelegate reflect".PadRight(20) + " : " + tick);
Console.ReadKey();
}
delegate void SetValueHandler(Int32 value);
public class TestClass
{
private int _value = 500;
public int Value
{
get
{
return _value;
}
set
{
_value = value;
//Console.WriteLine("Value changed! New value is " + value.ToString());
}
}
}
/// <summary>
/// 设置Protected/Private类型的属性值
/// </summary>
/// <param name="Owner">要设置的对象</param>
/// <param name="propertyName">属性名</param>
/// <param name="value">值</param>
public static void SetNonePublicPropertyValue(object Owner, string propertyName, object value)
{
//Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).ToList().ForEach(p => Console.WriteLine(p.Name));
//获取非公开的成员属性
PropertyInfo pi = Owner.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default);
if (pi != null)//如果获取到了,说明你调用没错
{
pi.SetValue(Owner, value, null);//设置值,这个最后一个属性,是索引值,如果属性本身是Array或List,这里要写索引编号或索引器要求的值。
}
}
/// <summary>
/// 缓存反射结果的类,提高访问速度
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class FastPropertyBufferd<T>
{
private T _owner = default(T);
MethodInfo mi = null;
public FastPropertyBufferd(T owner, string propertyName)
{
_owner = owner;
mi = typeof(T).GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
}
public void SetValue(object value)
{
mi.Invoke(_owner, new object[] { value });
}
}
public class FastProperty<T>
{
public delegate void SetValueDelegateHandler(T owner, object value);
private readonly Type ParameterType = typeof(object);
private T _owner;
public T Owner { get { return this._owner; } }
private Type _ownerType;
public FastProperty(T owner)
{
this._owner = owner;
this._ownerType = typeof(T);
}
public void SetPropertyValue2(string propertyName, object value)
{
PropertyInfo[] pis = Owner.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (PropertyInfo pi in pis)
{
if (pi.Name == propertyName)
{
pi.SetValue(Owner, value, null);
}
}
}
public SetValueDelegateHandler SetPropertyValue(string propertyName, object value)
{
// 指定函数名
string methodName = "set_" + propertyName;
// 搜索函数,不区分大小写 IgnoreCase
MethodInfo callMethod = this._ownerType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
// 获取参数
ParameterInfo para = callMethod.GetParameters()[0];
// 创建动态函数
DynamicMethod method = new DynamicMethod("EmitCallable", null, new Type[] { this._ownerType, ParameterType }, this._ownerType.Module);
// 获取动态函数的 IL 生成器
ILGenerator il = method.GetILGenerator();
// 创建一个本地变量,主要用于 Object Type to Propety Type
LocalBuilder local = il.DeclareLocal(para.ParameterType, true);
// 加载第 2 个参数【(T owner, object value)】的 value
il.Emit(OpCodes.Ldarg_1);
if (para.ParameterType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
}
else
{
il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
}
il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
il.Emit(OpCodes.Ldloc, local);// 加载本地参数
il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
il.Emit(OpCodes.Ret); // 返回
/* 生成的动态函数类似:
* void EmitCallable(T owner, object value)
* {
* T local = (T)value;
* owner.Method(local);
* }
*/
return method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
}
}
}