C#各种反射动态赋值取值方法

 

简单代码示例:

1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Web;
5  using System.Web.UI;
6  using System.Web.UI.WebControls;
7  using System.Data;
8 using KaiCommon;
9 using System.Reflection;
10 using KaiCommon.ORM;
11 using System.Linq.Expressions;
12 using System.Reflection.Emit;
13
14 public delegate void PropertySetter<T>(T value);
15 public delegate T PropertyGetter<T>();
16
17 public partial class Tools_TestGrid : System.Web.UI.Page
18 {
19 #region 泛型委托实现
20 public PropertyGetter<int> PropGet;
21 public PropertySetter<int> PropSet;
22 public void BuildSetMethod(TestData td)
23 {
24 Type t = td.GetType();
25 PropertyInfo pi = t.GetProperty("Name");
26 MethodInfo setter = pi.GetSetMethod();
27
28 PropSet = (PropertySetter<int>)Delegate.CreateDelegate(typeof(PropertySetter<int>), td, setter);
29
30 //string value = strPropGetter();
31 }
32
33 public void BuildGetMethod(TestData td)
34 {
35 Type t = td.GetType();
36 PropertyInfo pi = t.GetProperty("Name");
37 MethodInfo getter = pi.GetGetMethod();
38
39 PropGet = (PropertyGetter<int>)Delegate.CreateDelegate(typeof(PropertyGetter<int>), td, getter);
40
41 //string value = strPropGetter();
42 }
43
44 #endregion
45
46 #region 表达式树实现
47 Func<object, int> LmdGetProp; //Func<TestData, int>
48 public void LmdGet(Type entityType, string propName)
49 {
50 #region 通过方法取值
51 var p = entityType.GetProperty(propName);
52 //对象实例
53 var param_obj = Expression.Parameter(typeof(object), "obj");
54 //
55 //var param_val = Expression.Parameter(typeof(object), "val");
56 //转换参数为真实类型
57 var body_obj = Expression.Convert(param_obj, entityType);
58
59 //调用获取属性的方法
60 var body = Expression.Call(body_obj, p.GetGetMethod());
61 LmdGetProp = Expression.Lambda<Func<object, int>>(body, param_obj).Compile();
62 #endregion
63
64 #region 表达式取值
65 //var p = entityType.GetProperty(propName);
66 ////lambda的参数u
67 //var param_u = Expression.Parameter(entityType, "u");
68 ////lambda的方法体 u.Age
69 //var pGetter = Expression.Property(param_u, p);
70 ////编译lambda
71 //LmdGetProp = Expression.Lambda<Func<TestData, int>>(pGetter, param_u).Compile();
72 #endregion
73 }
74 Action<object, object> LmdSetProp;
75 public void LmdSet(Type entityType, string propName)
76 {
77 var p = entityType.GetProperty(propName);
78 //对象实例
79 var param_obj = Expression.Parameter(typeof(object), "obj");
80 //
81 var param_val = Expression.Parameter(typeof(object), "val");
82 //转换参数为真实类型
83 var body_obj = Expression.Convert(param_obj, entityType);
84 var body_val = Expression.Convert(param_val, p.PropertyType);
85 //调用给属性赋值的方法
86 var body = Expression.Call(body_obj, p.GetSetMethod(), body_val);
87 LmdSetProp = Expression.Lambda<Action<object, object>>(body, param_obj, param_val).Compile();
88
89 }
90 #endregion
91
92
93 #region Emit动态方法实现
94 public delegate void SetValueDelegateHandler(TestData entity, object value);
95 public SetValueDelegateHandler EmitSetValue;
96 public void BuildEmitMethod(Type entityType, string propertyName)
97 {
98 //Type entityType = entity.GetType();
99 Type parmType = typeof(object);
100 // 指定函数名
101 string methodName = "set_" + propertyName;
102 // 搜索函数,不区分大小写 IgnoreCase
103 var callMethod = entityType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic);
104 // 获取参数
105 var para = callMethod.GetParameters()[0];
106 // 创建动态函数
107 DynamicMethod method = new DynamicMethod("EmitCallable", null, new Type[] { entityType, parmType }, entityType.Module);
108 // 获取动态函数的 IL 生成器
109 var il = method.GetILGenerator();
110 // 创建一个本地变量,主要用于 Object Type to Propety Type
111 var local = il.DeclareLocal(para.ParameterType, true);
112 // 加载第 2 个参数【(T owner, object value)】的 value
113 il.Emit(OpCodes.Ldarg_1);
114 if (para.ParameterType.IsValueType)
115 {
116 il.Emit(OpCodes.Unbox_Any, para.ParameterType);// 如果是值类型,拆箱 string = (string)object;
117 }
118 else
119 {
120 il.Emit(OpCodes.Castclass, para.ParameterType);// 如果是引用类型,转换 Class = object as Class
121 }
122 il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。
123 il.Emit(OpCodes.Ldarg_0); // 加载第一个参数 owner
124 il.Emit(OpCodes.Ldloc, local);// 加载本地参数
125 il.EmitCall(OpCodes.Callvirt, callMethod, null);//调用函数
126 il.Emit(OpCodes.Ret); // 返回
127 /* 生成的动态函数类似:
128 * void EmitCallable(T owner, object value)
129 * {
130 * T local = (T)value;
131 * owner.Method(local);
132 * }
133 */
134
135 EmitSetValue = method.CreateDelegate(typeof(SetValueDelegateHandler)) as SetValueDelegateHandler;
136
137 }
138 #endregion
139
140 protected void Page_Load(object sender, EventArgs e)
141 {
142
143 this.Response.Write("当前framework版本:" + Environment.Version.Major + "<br/>");
144 int max = 1000000;
145 this.Response.Write("循环次数:" + max + "<br/>");
146 if (!IsPostBack)
147 {
148 //基本方法
149 DateTime time = DateTime.Now;
150 TestData d = new TestData();
151 for (int i = 0; i < max; i++)
152 {
153 d.Name = i;
154 }
155 TimeSpan ts = DateTime.Now - time;
156 this.Response.Write("基本方法:" + ts.TotalMilliseconds + "<br/>");
157
158 //反射方法
159 Type type = d.GetType();
160 PropertyInfo pi = type.GetProperty("Name");
161 time = DateTime.Now;
162 for (int i = 0; i < max; i++)
163 {
164 pi.SetValue(d, i, null);
165 }
166 ts = DateTime.Now - time;
167 this.Response.Write("反射方法:" + ts.TotalMilliseconds + "<br/>");
168
169 //dynamic动态类型方法
170 dynamic dobj = Activator.CreateInstance<TestData>();
171 time = DateTime.Now;
172 for (int i = 0; i < max; i++)
173 {
174 dobj.Name = i;
175 }
176 ts = DateTime.Now - time;
177 this.Response.Write("dynamic动态类型方法:" + ts.TotalMilliseconds + "<br/>");
178
179 //泛型委托赋值方法
180 d.Name = -1;
181 BuildSetMethod(d);
182 time = DateTime.Now;
183 for (int i = 0; i < max; i++)
184 {
185 this.PropSet(i);
186 }
187 ts = DateTime.Now - time;
188 this.Response.Write("泛型委托赋值方法:" + ts.TotalMilliseconds + "<br/>");
189 this.Response.Write("v:" + d.Name + "<br/>");
190
191 //泛型委托取值方法
192 d.Name = -1;
193 BuildGetMethod(d);
194 time = DateTime.Now;
195 for (int i = 0; i < max; i++)
196 {
197 this.PropGet();
198 }
199 ts = DateTime.Now - time;
200 this.Response.Write("泛型委托取值方法:" + ts.TotalMilliseconds + "<br/>");
201 this.Response.Write("v:" + d.Name + "<br/>");
202
203 //表达式树赋值方法
204 d.Name = -1;
205 LmdSet(typeof(TestData), "Name");
206 time = DateTime.Now;
207 for (int i = 0; i < max; i++)
208 {
209 this.LmdSetProp(d, i);
210 }
211 ts = DateTime.Now - time;
212 this.Response.Write("表达式树赋值方法:" + ts.TotalMilliseconds + "<br/>");
213 this.Response.Write("v:" + d.Name + "<br/>");
214
215 //表达式树取值方法
216 d.Name = -132;
217 this.LmdGet(typeof(TestData), "Name");
218 time = DateTime.Now;
219 for (int i = 0; i < max; i++)
220 {
221 this.LmdGetProp(d);
222 }
223 ts = DateTime.Now - time;
224 this.Response.Write("表达式树取值方法:" + ts.TotalMilliseconds + "<br/>");
225 this.Response.Write("v:" + this.LmdGetProp(d) + "<br/>");
226
227 //EMIT动态方法赋值
228 d.Name = -1;
229 this.BuildEmitMethod(d.GetType(), "Name");
230 time = DateTime.Now;
231 for (int i = 0; i < max; i++)
232 {
233 this.EmitSetValue(d, i);
234 }
235 ts = DateTime.Now - time;
236 this.Response.Write("EMIT动态方法:" + ts.TotalMilliseconds + "<br/>");
237 this.Response.Write("v:" + d.Name + "<br/>");
238
239 //TestDataBind();
240 }
241 }
242
243 }
244
245 public class TestData
246 {
247 public int Name { get; set; }
248 }

 


posted @ 2010-06-09 10:35  David.Yang  阅读(15980)  评论(3编辑  收藏  举报