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 }

 


你可能感兴趣的:(C#)