C#各种反射动态赋值取值方法
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using KaiCommon; using System.Reflection; using KaiCommon.ORM; using System.Linq.Expressions; using System.Reflection.Emit; public delegate void PropertySetter<T>(T value); public delegate T PropertyGetter<T>(); public partial class Tools_TestGrid : System.Web.UI.Page { #region 泛型委托实现 public PropertyGetter<int> PropGet; public PropertySetter<int> PropSet; public void BuildSetMethod(TestData td) { Type t = td.GetType(); PropertyInfo pi = t.GetProperty("Name"); MethodInfo setter = pi.GetSetMethod(); PropSet = (PropertySetter<int>)Delegate.CreateDelegate(typeof(PropertySetter<int>), td, setter); //string value = strPropGetter(); } public void BuildGetMethod(TestData td) { Type t = td.GetType(); PropertyInfo pi = t.GetProperty("Name"); MethodInfo getter = pi.GetGetMethod(); PropGet = (PropertyGetter<int>)Delegate.CreateDelegate(typeof(PropertyGetter<int>), td, getter); //string value = strPropGetter(); } #endregion #region 表达式树实现 Func<object, int> LmdGetProp; //Func<TestData, int> public void LmdGet(Type entityType, string propName) { #region 通过方法取值 var p = entityType.GetProperty(propName); //对象实例 var param_obj = Expression.Parameter(typeof(object), "obj"); //值 //var param_val = Expression.Parameter(typeof(object), "val"); //转换参数为真实类型 var body_obj = Expression.Convert(param_obj, entityType); //调用获取属性的方法 var body = Expression.Call(body_obj, p.GetGetMethod()); LmdGetProp = Expression.Lambda<Func<object, int>>(body, param_obj).Compile(); #endregion #region 表达式取值 //var p = entityType.GetProperty(propName); ////lambda的参数u //var param_u = Expression.Parameter(entityType, "u"); ////lambda的方法体 u.Age //var pGetter = Expression.Property(param_u, p); ////编译lambda //LmdGetProp = Expression.Lambda<Func<TestData, int>>(pGetter, param_u).Compile(); #endregion } Action<object, object> LmdSetProp; public void LmdSet(Type entityType, string propName) { var p = entityType.GetProperty(propName); //对象实例 var param_obj = Expression.Parameter(typeof(object), "obj"); //值 var param_val = Expression.Parameter(typeof(object), "val"); //转换参数为真实类型 var body_obj = Expression.Convert(param_obj, entityType); var body_val = Expression.Convert(param_val, p.PropertyType); //调用给属性赋值的方法 var body = Expression.Call(body_obj, p.GetSetMethod(), body_val); LmdSetProp = Expression.Lambda<Action<object, object>>(body, param_obj, param_val).Compile(); } #endregion #region Emit动态方法实现 public delegate void SetValueDelegateHandler(TestData entity, object value); public SetValueDelegateHandler EmitSetValue; public void BuildEmitMethod(Type entityType, string propertyName) { //Type entityType = entity.GetType(); Type parmType = typeof(object); // 指定函数名 string methodName = "set_" + propertyName; // 搜索函数,不区分大小写 IgnoreCase var callMethod = entityType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic); // 获取参数 var para = callMethod.GetParameters()[0]; // 创建动态函数 DynamicMethod method = new DynamicMethod("EmitCallable", null, new Type[] { entityType, parmType }, entityType.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); * } */ EmitSetValue = method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler; } #endregion protected void Page_Load(object sender, EventArgs e) { this.Response.Write("当前framework版本:" + Environment.Version.Major + "<br/>"); int max = 1000000; this.Response.Write("循环次数:" + max + "<br/>"); if (!IsPostBack) { //基本方法 DateTime time = DateTime.Now; TestData d = new TestData(); for (int i = 0; i < max; i++) { d.Name = i; } TimeSpan ts = DateTime.Now - time; this.Response.Write("基本方法:" + ts.TotalMilliseconds + "<br/>"); //反射方法 Type type = d.GetType(); PropertyInfo pi = type.GetProperty("Name"); time = DateTime.Now; for (int i = 0; i < max; i++) { pi.SetValue(d, i, null); } ts = DateTime.Now - time; this.Response.Write("反射方法:" + ts.TotalMilliseconds + "<br/>"); //dynamic动态类型方法 dynamic dobj = Activator.CreateInstance<TestData>(); time = DateTime.Now; for (int i = 0; i < max; i++) { dobj.Name = i; } ts = DateTime.Now - time; this.Response.Write("dynamic动态类型方法:" + ts.TotalMilliseconds + "<br/>"); //泛型委托赋值方法 d.Name = -1; BuildSetMethod(d); time = DateTime.Now; for (int i = 0; i < max; i++) { this.PropSet(i); } ts = DateTime.Now - time; this.Response.Write("泛型委托赋值方法:" + ts.TotalMilliseconds + "<br/>"); this.Response.Write("v:" + d.Name + "<br/>"); //泛型委托取值方法 d.Name = -1; BuildGetMethod(d); time = DateTime.Now; for (int i = 0; i < max; i++) { this.PropGet(); } ts = DateTime.Now - time; this.Response.Write("泛型委托取值方法:" + ts.TotalMilliseconds + "<br/>"); this.Response.Write("v:" + d.Name + "<br/>"); //表达式树赋值方法 d.Name = -1; LmdSet(typeof(TestData), "Name"); time = DateTime.Now; for (int i = 0; i < max; i++) { this.LmdSetProp(d, i); } ts = DateTime.Now - time; this.Response.Write("表达式树赋值方法:" + ts.TotalMilliseconds + "<br/>"); this.Response.Write("v:" + d.Name + "<br/>"); //表达式树取值方法 d.Name = -132; this.LmdGet(typeof(TestData), "Name"); time = DateTime.Now; for (int i = 0; i < max; i++) { this.LmdGetProp(d); } ts = DateTime.Now - time; this.Response.Write("表达式树取值方法:" + ts.TotalMilliseconds + "<br/>"); this.Response.Write("v:" + this.LmdGetProp(d) + "<br/>"); //EMIT动态方法赋值 d.Name = -1; this.BuildEmitMethod(d.GetType(), "Name"); time = DateTime.Now; for (int i = 0; i < max; i++) { this.EmitSetValue(d, i); } ts = DateTime.Now - time; this.Response.Write("EMIT动态方法:" + ts.TotalMilliseconds + "<br/>"); this.Response.Write("v:" + d.Name + "<br/>"); //TestDataBind(); } } } public class TestData { public int Name { get; set; } }