日期:2014-05-20 浏览次数:21071 次
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; } } }