c# 为实体赋值通过直接赋值,Emit,反射三种方法测试

 1  public class Class1
 2     {
 3         public static void Button_Click()
 4         {
 5             TestDemoEntity entity;
 6             Stopwatch watch;
 7             int length = 1000000;
 8 
 9             #region 直接赋值    1
10             watch = new Stopwatch();
11             watch.Start();
12             entity = new TestDemoEntity();
13             for (int i = 0; i < length; i++)
14             {
15                 entity.Name = "测试";
16             }
17             watch.Start();
18             Console.WriteLine("直接赋值:" + watch.ElapsedMilliseconds);
19             #endregion
20 
21             #region 通过Emit赋值    2
22             watch = new Stopwatch();
23             watch.Start();
24             entity = new TestDemoEntity();
25             var emitSetter = EmitSetter<TestDemoEntity>("Name");
26             for (int i = 0; i < length; i++)
27             {
28                 emitSetter(entity, "测试" + i);
29             }
30             watch.Start();
31             Console.WriteLine("通过Emit赋值:" + watch.ElapsedMilliseconds);
32 
33             #endregion
34 
35             #region 通过反射赋值  3
36             watch = new Stopwatch();
37             watch.Start();
38             entity = new TestDemoEntity();
39             for (int i = 0; i < length; i++)
40             {
41                 ReflectSetter(entity, "Name", "测试");
42             }
43             watch.Start();
44             Console.WriteLine("通过反射赋值:" + watch.ElapsedMilliseconds);
45 
46             #endregion
47         }
48 
49         public static Action<T, object> EmitSetter<T>(string propertyName)
50         {
51             var type = typeof(T);
52             var dynamicMethod = new DynamicMethod("EmitCallable", null, new[] { type, typeof(object) }, type.Module);//定义和表示一个可以编译,执行和丢弃的动态方法
53             var iLGenerator = dynamicMethod.GetILGenerator();//返回方法的Microsoft中间语言(MSIL)生成器,默认的MSIL流大小为64字节
54             if (iLGenerator != null)
55             {
56                 var callMethod = type.GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);//获取字段set属性
57                 if (callMethod != null)
58                 {
59                     var parameterInfo = callMethod.GetParameters()[0];
60                     if (parameterInfo != null)
61                     {
62                         var local = iLGenerator.DeclareLocal(parameterInfo.ParameterType, true);
63                         #region Emit()将指定的指令放在指令流上,该方法接收一个IL流。EmitCall()将 call 或 callvirt 指令置于 Microsoft 中间语言 (MSIL) 流,以调用varargs 方法。我们看到OpCodes类,该类描述中间语言 (IL) 指令
64                         iLGenerator.Emit(OpCodes.Ldarg_1);
65                         if (parameterInfo.ParameterType.IsValueType)
66                         {
67                             // 如果是值类型,拆箱
68                             iLGenerator.Emit(OpCodes.Unbox_Any, parameterInfo.ParameterType);
69                         }
70                         else
71                         {
72                             // 如果是引用类型,转换
73                             iLGenerator.Emit(OpCodes.Castclass, parameterInfo.ParameterType);
74                         }
75                         iLGenerator.Emit(OpCodes.Stloc, local);//OpCodes类,该类描述中间语言 (IL) 指令
76                         iLGenerator.Emit(OpCodes.Ldarg_0);//将指定的指令放在指令流上,该方法接收一个IL流
77                         iLGenerator.Emit(OpCodes.Ldloc, local);
78                         iLGenerator.EmitCall(OpCodes.Callvirt, callMethod, null);//将 call 或 callvirt 指令置于 Microsoft 中间语言 (MSIL) 流,以调用varargs 方法
79                         iLGenerator.Emit(OpCodes.Ret); 
80                         #endregion
81                     }
82                 }
83             }
84             return dynamicMethod.CreateDelegate(typeof(Action<T, object>)) as Action<T, object>;//CreateDelegate()完成动态方法并创建一个可用于执行它的委托。
85         }
86         public static void ReflectSetter(object obj, string propertyName, object propertyValue)
87         {
88             var type = obj.GetType();
89             var propertyInfo = type.GetProperty(propertyName);
90             propertyInfo.SetValue(obj, propertyValue, null);
91         }
92     }
93     public class TestDemoEntity
94     {
95         public string Name { get; set; }
96     }

原文地址:https://www.cnblogs.com/aaaaq/p/8643381.html