您的位置:时时app平台注册网站 > 编程知识 > 收获分享(-) — 利用Emit生成实体【时时app平台

收获分享(-) — 利用Emit生成实体【时时app平台

2019-12-06 10:44

  测量试验代码:

  第叁次写博客,也不知该写点什么好,不及把多年来鼓捣的名堂分享一下,独乐乐比不上众乐乐!

时时app平台注册网站 1时时app平台注册网站 2

时时app平台注册网站 3时时app平台注册网站 4

1、MyType.cs

2、测验方法

时时app平台注册网站 5时时app平台注册网站 6

时时app平台注册网站 7时时app平台注册网站 8

时时app平台注册网站 9时时app平台注册网站 10

  相当多代码,也是借鉴广大网络基友分享的名堂而来,在这里表示谢谢!

View Code

时时app平台注册网站 11时时app平台注册网站 12

 1  static List<Model.User2> DataTableHand(DataTable table)
 2         {
 3             int rows = null == table ? 0 : table.Rows.Count   1;
 4             if (1 < rows)
 5             {
 6                 try
 7                 {
 8                     List<Model.User2> list = new List<Model.User2>(rows);
 9                     foreach(DataRow row in table.Rows)
10                     {
11                         list.Add(Model.UserFactory.GetUser(row));
12                     }
13                     return list;
14                 }
15                 catch
16                 {
17                 }
18             }
19             return null;
20         }
21 
22         static void Test()
23         {
24             CodeTimer.Initialize();
25             // 预热
26             DataTable tbale1 = db2.GetDataTable("SELECT uid,mobile,realname,regTime, orig_src,referrerid, referrername FROM users LIMIT 1");
27             var obj6 = MyDataTable<Model.User2>.ToList(tbale1);
28             DataTable table2 = db2.GetDataTable("SELECT uid,mobile,realname,regTime, orig_src,referrerid, referrername FROM users LIMIT 419196");
29             CodeTimer.Time("手写:", 1, () => { DataTableHand(table2); });
30             CodeTimer.Time("Emit:", 1, () => { MyDataTable<Model.User2>.ToList(table2); });
31         }

7、MyDataReader.cs

时时app平台注册网站 13时时app平台注册网站 14

View Code

 1 using System;
 2 using System.Reflection;
 3 
 4 namespace Mapper
 5 {
 6     public struct DbColumn
 7     {
 8         public readonly string Name;
 9 
10         public readonly Type DataType;
11 
12         public readonly MethodInfo ConvertMethod;
13 
14         public readonly MethodInfo SetMethod;
15 
16         public DbColumn(string name, Type type, MethodInfo setMethod, MethodInfo convertMethod)
17         {
18             Name           = name;
19             DataType       = type;
20             ConvertMethod  = convertMethod;
21             SetMethod      = setMethod;
22         }
23     }
24 }
  1 using System;
  2 using System.IO;
  3 using System.Runtime.Serialization;
  4 using System.Runtime.Serialization.Formatters.Binary;
  5 
  6 namespace Mapper
  7 {
  8     public static class MyConvert
  9     {
 10         private static readonly IFormatter formatter = new BinaryFormatter();
 11 
 12         #region 值类型
 13         public static bool ToBoolean(object value)
 14         {
 15             if (value != DBNull.Value)
 16             {
 17                 try
 18                 {
 19                     return Convert.ToBoolean(value);
 20                 }
 21                 catch
 22                 {
 23                 }
 24             }
 25             return false;
 26         }
 27 
 28         public static char ToChar(object value)
 29         {
 30             if (value != DBNull.Value)
 31             {
 32                 try
 33                 {
 34                     string str = Convert.ToString(value); 
 35                     if(null != str && 0 < str.Length)
 36                     {
 37                         return str[0];
 38                     }
 39                 }
 40                 catch
 41                 {
 42                 }
 43             }
 44             return '\0';
 45         }
 46 
 47         public static sbyte ToSByte(object value)
 48         {
 49             if (value != DBNull.Value)
 50             {
 51                 try
 52                 {
 53                     return Convert.ToSByte(value);
 54                 }
 55                 catch
 56                 {
 57                 }
 58             }
 59             return 0;
 60         }
 61 
 62         public static byte ToByte(object value)
 63         {
 64             if (value != DBNull.Value)
 65             {
 66                 try
 67                 {
 68                     return Convert.ToByte(value);
 69                 }
 70                 catch
 71                 {
 72                 }
 73             }
 74             return 0;
 75         }
 76 
 77         public static short ToInt16(object value)
 78         {
 79             if (value != DBNull.Value)
 80             {
 81                 try
 82                 {
 83                     return Convert.ToInt16(value);
 84                 }
 85                 catch
 86                 {
 87                 }
 88             }
 89             return 0;
 90         }
 91 
 92         public static ushort ToUInt16(object value)
 93         {
 94             if (value != DBNull.Value)
 95             {
 96                 try
 97                 {
 98                     return Convert.ToUInt16(value);
 99                 }
100                 catch
101                 {
102                 }
103             }
104             return 0;
105         }
106 
107         public static int ToInt32(object value)
108         {
109             if (value != DBNull.Value)
110             {
111                 try
112                 {
113                     return Convert.ToInt32(value);
114                 }
115                 catch
116                 {
117                 }
118             }
119             return 0;
120         }
121 
122         public static uint ToUInt32(object value)
123         {
124             if (value != DBNull.Value)
125             {
126                 try
127                 {
128                     return Convert.ToUInt32(value);
129                 }
130                 catch
131                 {
132                 }
133             }
134             return 0;
135         }
136 
137         public static long ToInt64(object value)
138         {
139             if (value != DBNull.Value)
140             {
141                 try
142                 {
143                     return Convert.ToInt64(value);
144                 }
145                 catch
146                 {
147                 }
148             }
149             return 0;
150         }
151 
152         public static ulong ToUInt64(object value)
153         {
154             if (value != DBNull.Value)
155             {
156                 try
157                 {
158                     return Convert.ToUInt64(value);
159                 }
160                 catch
161                 {
162                 }
163             }
164             return 0;
165         }
166 
167         public static float ToSingle(object value)
168         {
169             if (value != DBNull.Value)
170             {
171                 try
172                 {
173                     return Convert.ToSingle(value);
174                 }
175                 catch
176                 {
177                 }
178             }
179             return 0f;
180         }
181 
182         public static decimal ToDecimal(object value)
183         {
184             if (value != DBNull.Value)
185             {
186                 try
187                 {
188                     return Convert.ToDecimal(value);
189                 }
190                 catch
191                 {
192                 }
193             }
194             return 0m;
195         }
196 
197         public static double ToDouble(object value)
198         {
199             if (value != DBNull.Value)
200             {
201                 try
202                 {
203                     return Convert.ToDouble(value);
204                 }
205                 catch
206                 {
207                 }
208             }
209             return 0d;
210         }
211 
212         public static DateTime ToDateTime(object value)
213         {
214             if (value != DBNull.Value)
215             {
216                 try
217                 {
218                     return Convert.ToDateTime(value);
219                 }
220                 catch
221                 {
222                 }
223             }
224             return DateTime.MinValue;
225         }
226 
227         public static DateTimeOffset ToDateTimeOffset(object value)
228         {
229             if (value != DBNull.Value)
230             {
231                 try
232                 {
233                     return (DateTimeOffset)value;
234                 }
235                 catch
236                 {
237                 }
238             }
239             return DateTimeOffset.MinValue;
240         }
241         public static DateTimeOffset? ToDateTimeOffsetNullable(object value)
242         {
243             if (value != DBNull.Value)
244             {
245                 try
246                 {
247                     return (DateTimeOffset)value;
248                 }
249                 catch
250                 {
251                 }
252             }
253             return null;
254         }
255         #endregion
256 
257         #region 引用类型
258         public static object ToObject(object value)
259         {
260             return value;
261         }
262 
263         public static bool? ToBooleanNullable(object value)
264         {
265             if (null != value && value != DBNull.Value)
266             {
267                 try
268                 {
269                     return Convert.ToBoolean(value);
270                 }
271                 catch
272                 {
273                 }
274             }
275             return null;
276         }
277 
278         public static byte[] ToByteArray(object value)
279         {
280             if (null != value && value != DBNull.Value)
281             {
282                 MemoryStream stream = new MemoryStream();
283                 try
284                 {
285                     formatter.Serialize(stream, value);
286                     return stream.GetBuffer();
287                 }
288                 finally
289                 {
290                     stream.Dispose();
291                 }
292             }
293             return null;
294         }
295 
296         public static char? ToCharNullable(object value)
297         {
298             if (null != value && value != DBNull.Value)
299             {
300                 try
301                 {
302                     string str = Convert.ToString(value);
303                     if (null != str && 0 < str.Length)
304                     {
305                         return str[0];
306                     }
307                 }
308                 catch
309                 {
310                 }
311             }
312             return null;
313         }
314 
315         public static Guid ToGuid(object value)
316         {
317             if (null != value && value != DBNull.Value)
318             {
319                 try
320                 {
321                     return (Guid)value;
322                 }
323                 catch
324                 {
325                 }
326             }
327             return Guid.Empty;
328         }
329 
330         public static byte? ToByteNullable(object value)
331         {
332             if (null != value && value != DBNull.Value)
333             {
334                 try
335                 {
336                     return Convert.ToByte(value);
337                 }
338                 catch
339                 {
340                 }
341             }
342             return null;
343         }
344 
345         public static sbyte? ToSByteNullable(object value)
346         {
347             if (null != value && value != DBNull.Value)
348             {
349                 try
350                 {
351                     return Convert.ToSByte(value);
352                 }
353                 catch
354                 {
355                 }
356             }
357             return null;
358         }
359 
360         public static short? ToInt16Nullable(object value)
361         {
362             if (null != value && value != DBNull.Value)
363             {
364                 try
365                 {
366                     return Convert.ToInt16(value);
367                 }
368                 catch
369                 {
370                 }
371             }
372             return null;
373         }
374 
375         public static ushort? ToUInt16Nullable(object value)
376         {
377             if (null != value && value != DBNull.Value)
378             {
379                 try
380                 {
381                     return Convert.ToUInt16(value);
382                 }
383                 catch
384                 {
385                 }
386             }
387             return null;
388         }
389 
390         public static int? ToInt32Nullable(object value)
391         {
392             if (null != value && value != DBNull.Value)
393             {
394                 try
395                 {
396                     return Convert.ToInt32(value);
397                 }
398                 catch
399                 {
400                 }
401             }
402             return null;
403         }
404 
405         public static uint? ToUInt32Nullable(object value)
406         {
407             if (null != value && value != DBNull.Value)
408             {
409                 try
410                 {
411                     return Convert.ToUInt32(value);
412                 }
413                 catch
414                 {
415                 }
416             }
417             return null;
418         }
419 
420         public static long? ToInt64Nullable(object value)
421         {
422             if (null != value && value != DBNull.Value)
423             {
424                 try
425                 {
426                     return Convert.ToInt64(value);
427                 }
428                 catch
429                 {
430                 }
431             }
432             return null;
433         }
434 
435         public static ulong? ToUInt64Nullable(object value)
436         {
437             if (null != value && value != DBNull.Value)
438             {
439                 try
440                 {
441                     return Convert.ToUInt64(value);
442                 }
443                 catch
444                 {
445                 }
446             }
447             return null;
448         }
449 
450         public static float? ToSingleNullable(object value)
451         {
452             if (null != value && value != DBNull.Value)
453             {
454                 try
455                 {
456                     return Convert.ToSingle(value);
457                 }
458                 catch
459                 {
460                 }
461             }
462             return null;
463         }
464 
465         public static decimal? ToDecimalNullable(object value)
466         {
467             if (null != value && value != DBNull.Value)
468             {
469                 try
470                 {
471                     return Convert.ToDecimal(value);
472                 }
473                 catch
474                 {
475                 }
476             }
477             return null;
478         }
479 
480         public static double? ToDoubleNullable(object value)
481         {
482             if (null != value && value != DBNull.Value)
483             {
484                 try
485                 {
486                     return Convert.ToDouble(value);
487                 }
488                 catch
489                 {
490                 }
491             }
492             return null;
493         }
494 
495         public static DateTime? ToDateTimeNullable(object value)
496         {
497             if (null != value && value != DBNull.Value)
498             {
499                 try
500                 {
501                     return Convert.ToDateTime(value);
502                 }
503                 catch
504                 {
505                 }
506             }
507             return null;
508         }
509 
510         public static Guid? ToGuidNullable(object value)
511         {
512             if (null != value && value != DBNull.Value)
513             {
514                 try
515                 {
516                     return (Guid)value;
517                 }
518                 catch
519                 {
520                 }
521             }
522             return null;
523         }
524         #endregion
525 
526         #region 其他
527         public static int IndexOf(int length, string[] fields, string name)
528         {
529             for (int index = 0; index < length; index  )
530             {
531                 if (string.Equals(fields[index], name, StringComparison.OrdinalIgnoreCase))
532                 {
533                     return index;
534                 }
535             }
536             return -1;
537         }
538         #endregion
539 
540     }
541 }

时时app平台注册网站 15时时app平台注册网站 16

 1 using System;
 2 using System.Reflection;
 3 using System.Collections.Generic;
 4 
 5 namespace Mapper
 6 {
 7     public class TypeHelper
 8     {
 9         internal static Type GetNullableEnum(Type type)
10         {
11             if (type == MyType.Byte)
12             {
13                 return MyType.NullableByte;
14             }
15 
16             if (type == MyType.SByte)
17             {
18                 return MyType.NullableSByte;
19             }
20 
21             if (type == MyType.Int16)
22             {
23                 return MyType.NullableInt16;
24             }
25 
26             if (type == MyType.Int32)
27             {
28                 return MyType.NullableInt32;
29             }
30 
31             return MyType.NullableInt32;
32         }
33 
34         public static List<DbColumn> GetCanSetColumns(Type type)
35         {
36             Type dataType, tempType;
37             List<DbColumn> result = new List<DbColumn>();
38             foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase))
39             {
40                 MethodInfo setMethod = prop.GetSetMethod(true);
41                 if (null == setMethod)
42                 {
43                     continue;
44                 }
45 
46                 DbColumnAttribute attr = Attribute.GetCustomAttribute(prop, MyType.DbColumn, true) as DbColumnAttribute;
47                 if (null == attr)
48                 {
49                     attr = new DbColumnAttribute();
50                 }
51 
52                 dataType = prop.PropertyType;
53                 if (dataType.IsGenericType)
54                 {
55                     if (string.Equals(dataType.Name, "Nullable`1"))
56                     {
57                         tempType = Nullable.GetUnderlyingType(dataType);
58                         if (tempType.IsEnum)
59                         {
60                             dataType = GetNullableEnum(Enum.GetUnderlyingType(tempType));
61                         }
62                     }
63                 }
64                 else if (dataType.IsEnum)
65                 {
66                     dataType = Enum.GetUnderlyingType(dataType);
67                 }
68 
69                 MethodInfo convertMethod = Method.Get(dataType);
70                 if (null != convertMethod)
71                 {
72                     result.Add(new DbColumn(attr.Name ?? prop.Name, dataType, setMethod, convertMethod));
73                 }
74             }
75             return result;
76         }
77 
78     }
79 }

2、MyConvert.cs

8、MyDataTable.cs

View Code

 

  Emit,就如个顽皮的幼童,难调教。初时,叁个头四个大,前边才意识这货吃硬不吃软,只可以是手写等效C#代码,然后模仿生成的IL代码,尽管经过有一些波折,但孩子不听话,毕竟要求教育指点。

  1 using System;
  2 using System.Data;
  3 using System.Reflection;
  4 using System.Reflection.Emit;
  5 using System.Collections.Generic;
  6 using System.Collections.Concurrent;
  7 
  8 namespace Mapper
  9 {
 10     public class MyDataReader<T>
 11     {
 12 
 13         #region 变量
 14 
 15         private delegate T SingleHandler(IDataReader dr, int fieldCount);
 16 
 17         private delegate List<T> ListHandler(IDataReader dr, int fieldCount);
 18 
 19         private const int MAX_CACHE_COUNT = 10000;
 20 
 21         private static readonly Type
 22             typeToSingle = typeof(SingleHandler),
 23             typeToList   = typeof(ListHandler);
 24        
 25         private static readonly ConcurrentDictionary<string, SingleHandler> 
 26             dictSingle   = new ConcurrentDictionary<string, SingleHandler>(StringComparer.OrdinalIgnoreCase);
 27 
 28         private static readonly ConcurrentDictionary<string, ListHandler> 
 29             dictList     = new ConcurrentDictionary<string, ListHandler>(StringComparer.OrdinalIgnoreCase);
 30 
 31         #endregion
 32 
 33         #region ToList
 34         public static List<T> ToList(IDataReader reader)
 35         {
 36             int cols = null == reader ? 0 : reader.FieldCount;
 37             if (0 < cols)
 38             {
 39                 try
 40                 {
 41                     Type type   = typeof(T);
 42                     string key  = type.FullName;
 43                     ListHandler handler;
 44                     dictList.TryGetValue(key, out handler);
 45                     if (null != handler)
 46                     {
 47                         return handler(reader, cols);
 48                     }
 49                     if (dictList.Count > MAX_CACHE_COUNT)
 50                     {
 51                         dictList.Clear();
 52                     }
 53                     handler = GetListHandler(type, key);
 54                     if (null != handler)
 55                     {
 56                         return handler(reader, cols);
 57                     }
 58                 }
 59                 catch (Exception ex)
 60                 {
 61                     #if DEBUG
 62                         throw ex;
 63                     #endif
 64                     // Log.XXX(ex);
 65                 }
 66             }
 67             return null;
 68         }
 69 
 70         private static ListHandler GetListHandler(Type type, string key)
 71         {
 72             Type typeList        = typeof(List<T>);
 73             DynamicMethod method = new DynamicMethod(string.Empty, typeList, new Type[] { MyType.IDataReader, MyType.Int32 }, true);
 74             ILGenerator il       = method.GetILGenerator();
 75             //List<T> list = new List<T>();
 76             il.DeclareLocal(typeList);
 77             il.Emit(OpCodes.Newobj, typeList.GetConstructor(Type.EmptyTypes));
 78             il.Emit(OpCodes.Stloc_0);
 79             Bind(il, typeList, type);
 80             // return list;
 81             il.Emit(OpCodes.Ldloc_0);
 82             il.Emit(OpCodes.Ret);
 83             // set cache
 84             ListHandler Handler = method.CreateDelegate(typeToList) as ListHandler;
 85             dictList[key]     = Handler;
 86             return Handler;
 87         }
 88 
 89         private static void Bind(ILGenerator il, Type list, Type item)
 90         {
 91             if (item.IsValueType)
 92             {
 93                 if (item.IsEnum)
 94                 {
 95                     item = Enum.GetUnderlyingType(item);
 96                 }
 97                 else if (string.Equals(item.Name, "Nullable`1"))
 98                 {
 99                     Type tempType = Nullable.GetUnderlyingType(item);
100                     if (tempType.IsEnum)
101                     {
102                         item = TypeHelper.GetNullableEnum(Enum.GetUnderlyingType(tempType));
103                     }
104                 }
105                 BindOther(il, item, list.GetMethod("Add"));
106             }
107             else if (item == MyType.String)
108             {
109                 BindOther(il, item, list.GetMethod("Add"));
110             }
111             else if (item == MyType.Object)
112             {
113                 BindOther(il, item, list.GetMethod("Add"), false);
114             }
115             else
116             {
117                 ConstructorInfo constructor = item.GetConstructor(Type.EmptyTypes);
118                 if (null != constructor)
119                 {
120                     BindClass(il, item, list.GetMethod("Add"), constructor);
121                 }
122             }
123         }
124 
125         private static void BindClass(ILGenerator il,Type type, MethodInfo add, ConstructorInfo constructor)
126         {
127             List<DbColumn> columns = TypeHelper.GetCanSetColumns(type);
128             int count              = columns.Count;
129             Label loop             = il.DefineLabel();
130             Label exit             = il.DefineLabel();
131             //T t -> 索引:1
132             il.DeclareLocal(type);
133             // 获取列索引
134             GetColumnIndices(il, columns, count);
135             // while (dr.Read()) {
136             il.MarkLabel(loop);
137             il.Emit(OpCodes.Ldarg_0);
138             il.Emit(OpCodes.Callvirt, Method.DataReader_Read);
139             il.Emit(OpCodes.Brfalse,  exit);
140              BuildItem(il, columns, type, count, constructor);
141             //list.Add(item(
142             il.Emit(OpCodes.Ldloc_0);
143             il.Emit(OpCodes.Ldloc_1);
144             il.Emit(OpCodes.Callvirt, add);
145             // }
146             il.Emit(OpCodes.Br, loop);
147             il.MarkLabel(exit);
148         }
149 
150         private static void BindOther(ILGenerator il, Type type, MethodInfo add, bool needConvert = true)
151         {
152             MethodInfo convertMethod = null;
153             if (needConvert)
154             {
155                 convertMethod = Method.Get(type);
156                 if(null== convertMethod)
157                 {
158                     return;
159                 }
160             }
161             Label loop = il.DefineLabel();
162             Label exit = il.DefineLabel();
163             // while (dr.Read()) {
164             il.MarkLabel(loop);
165             il.Emit(OpCodes.Ldarg_0);
166             il.Emit(OpCodes.Callvirt, Method.DataReader_Read);
167             il.Emit(OpCodes.Brfalse, exit);
168             //list.Add(MyConvert.ToXXX(dr.Getvalue(0)));
169             il.Emit(OpCodes.Ldloc_0);
170             il.Emit(OpCodes.Ldarg_0);
171             il.Emit(OpCodes.Ldc_I4_0);
172             il.Emit(OpCodes.Callvirt, Method.DataRecord_GetValue);
173             if (needConvert)
174             {
175                 il.Emit(OpCodes.Call, convertMethod);
176             }
177             il.Emit(OpCodes.Callvirt, add);
178             // }
179             il.Emit(OpCodes.Br, loop);
180             il.MarkLabel(exit);
181         }
182 
183         private static void GetColumnIndices(ILGenerator il, List<DbColumn> columns, int count)
184         {
185             // int index = 0;
186             il.DeclareLocal(MyType.Int32);
187             il.Emit(OpCodes.Ldc_I4_0);
188             il.Emit(OpCodes.Stloc_2);
189             // string[] fieldNames = new string[fieldCount];
190             il.DeclareLocal(MyType.StringArray);
191             il.Emit(OpCodes.Ldarg_1);
192             il.Emit(OpCodes.Newarr, MyType.String);
193             il.Emit(OpCodes.Stloc_3);
194 
195             Label loop = il.DefineLabel();
196             // for(; index < count; index  ) {fieldNames[i] = IDataRecord.GetName(index);}
197             il.MarkLabel(loop);
198             // fieldNames[index] 
199             il.Emit(OpCodes.Ldloc_3);
200             il.Emit(OpCodes.Ldloc_2);
201 
202             // = IDataRecord.GetName(index)
203             il.Emit(OpCodes.Ldarg_0);
204             il.Emit(OpCodes.Ldloc_2);
205             il.Emit(OpCodes.Callvirt, Method.DataRecord_GetName);
206             il.Emit(OpCodes.Stelem_Ref);
207 
208             // index  ;
209             il.Emit(OpCodes.Ldloc_2);
210             il.Emit(OpCodes.Ldc_I4_1);
211             il.Emit(OpCodes.Add);
212             il.Emit(OpCodes.Stloc_2);
213 
214             // if(index < fieldCount) { loop
215             il.Emit(OpCodes.Ldloc_2);
216             il.Emit(OpCodes.Ldarg_1);
217             il.Emit(OpCodes.Clt);
218             il.Emit(OpCodes.Brtrue, loop);
219 
220             for (int index = 0; index < count; index  )
221             {
222                 il.DeclareLocal(MyType.Int32);
223                 il.Emit(OpCodes.Ldarg_1); // fieldCount
224                 il.Emit(OpCodes.Ldloc_3); // fieldNames
225                 il.Emit(OpCodes.Ldstr, columns[index].Name);
226                 il.Emit(OpCodes.Call,  Method.String_IndexOf);
227                 il.Emit(OpCodes.Stloc, index   4);
228             }
229         }
230 
231         private static void BuildItem(ILGenerator il,  List<DbColumn> columns, Type type, int count, ConstructorInfo constructor)
232         {
233             il.Emit(OpCodes.Newobj, constructor);
234             il.Emit(OpCodes.Stloc_1);
235             for (int index = 0; index < count; index  )
236             {
237                 Label jump      = il.DefineLabel();
238                 DbColumn column = columns[index];
239                 // if(index == -1) { => go jump
240                 il.Emit(OpCodes.Ldloc,    index 4);
241                 il.Emit(OpCodes.Ldc_I4_M1);
242                 il.Emit(OpCodes.Ceq);
243                 il.Emit(OpCodes.Brtrue, jump);
244                 // T.xx = MyConvert.ToXXX(dr[index])
245                 il.Emit(OpCodes.Ldloc_1);
246                 il.Emit(OpCodes.Ldarg_0);
247                 il.Emit(OpCodes.Ldloc,    index 4);
248                 il.Emit(OpCodes.Callvirt, Method.DataRecord_GetValue);
249                 if (column.DataType != MyType.Object)
250                 {
251                     il.Emit(OpCodes.Call, column.ConvertMethod);
252                 }
253                 il.Emit(OpCodes.Callvirt, column.SetMethod);
254                 // }
255                 il.MarkLabel(jump);
256             }
257         }
258 
259         #endregion
260 
261         #region ToSingle
262         public static T ToSingle(IDataReader reader)
263         {
264             int cols = null == reader ? 0 : reader.FieldCount;
265             if (0 < cols)
266             {
267                 try
268                 {
269                     Type type  = typeof(T);
270                     string key = type.FullName;
271                     SingleHandler handler;
272                     dictSingle.TryGetValue(key, out handler);
273                     if (null != handler)
274                     {
275                         return handler(reader, cols);
276                     }
277                     if (dictSingle.Count > MAX_CACHE_COUNT)
278                     {
279                         dictSingle.Clear();
280                     }
281                     handler = GetSingleHandler(type, key);
282                     if (null != handler)
283                     {
284                         return handler(reader, cols);
285                     }
286                 }
287                 catch (Exception ex)
288                 {
289                     #if DEBUG
290                        throw ex;
291                     #endif 
292                        // Log.XXX(ex);
293                 }
294             }
295             return default(T);
296         }
297 
298         private static SingleHandler GetSingleHandler(Type type, string key)
299         {
300             DynamicMethod method = new DynamicMethod(string.Empty, type, new Type[] { MyType.IDataReader, MyType.Int32 }, true);
301             ILGenerator il       = method.GetILGenerator();
302             Label exit           = il.DefineLabel();
303             // T t
304             il.DeclareLocal(type);
305             // if (reader.Read()) {
306             il.Emit(OpCodes.Ldarg_0);
307             il.Emit(OpCodes.Callvirt, Method.DataReader_Read);
308             il.Emit(OpCodes.Brfalse, exit);
309             Bind(il, type);
310             // }
311             il.MarkLabel(exit);
312             // return 
313             il.Emit(OpCodes.Ldloc_0);
314             il.Emit(OpCodes.Ret);
315             SingleHandler Handler = method.CreateDelegate(typeToSingle) as SingleHandler;
316             dictSingle[key]     = Handler;
317             return Handler;
318         }
319 
320         private static void Bind(ILGenerator il, Type type)
321         {
322             if (type.IsValueType)
323             {
324                 if (type.IsEnum)
325                 {
326                     type = Enum.GetUnderlyingType(type);
327                 }
328                 else if (string.Equals(type.Name, "Nullable`1"))
329                 {
330                     Type tempType = Nullable.GetUnderlyingType(type);
331                     if (tempType.IsEnum)
332                     {
333                         type = TypeHelper.GetNullableEnum(Enum.GetUnderlyingType(tempType));
334                     }
335                 }
336                 BindOther(il, type);
337             }
338             else if (type == MyType.String)
339             {
340                 BindOther(il, type);
341             }
342             else if (type == MyType.Object)
343             {
344                 BindOther(il, type, false);
345             }
346             else
347             {
348                 ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
349                 if (null != constructor)
350                 {
351                     BindClass(il, type, constructor);
352                 }
353             }
354         }
355 
356         private static void BindOther(ILGenerator il, Type type, bool needConvert = true)
357         {
358             MethodInfo convertMethod = null;
359             if (needConvert)
360             {
361                 convertMethod = Method.Get(type);
362                 if (null == convertMethod)
363                 {
364                     return;
365                 }
366             }
367             //t = MyConvert.ToXXX(dr.Getvalue(0));
368             il.Emit(OpCodes.Ldarg_0);
369             il.Emit(OpCodes.Ldc_I4_0);
370             il.Emit(OpCodes.Callvirt, Method.DataRecord_GetValue);
371             if (needConvert)
372             {
373                 il.Emit(OpCodes.Call, convertMethod);
374             }
375             il.Emit(OpCodes.Stloc_0);
376         }
377 
378         private static void BindClass(ILGenerator il, Type type, ConstructorInfo constructor)
379         {
380             List<DbColumn> columns = TypeHelper.GetCanSetColumns(type);       
381             // T item = new T()
382             il.Emit(OpCodes.Newobj, constructor);
383             il.Emit(OpCodes.Stloc_0);
384 
385             #region string[] fieldNames = new string[fieldCount]
386             // int index = 0; 变量index索引: 1
387             il.DeclareLocal(MyType.Int32);
388             il.Emit(OpCodes.Ldc_I4_0);
389             il.Emit(OpCodes.Stloc_1);
390 
391             // string[] fieldNames = new string[fieldCount]; 索引2
392             il.DeclareLocal(MyType.StringArray);
393             il.Emit(OpCodes.Ldarg_1);
394             il.Emit(OpCodes.Newarr, MyType.String);
395             il.Emit(OpCodes.Stloc_2);
396 
397             // for(; index < count; index  ) {fieldNames[i] = IDataRecord.GetName(index);}
398             Label loop = il.DefineLabel();
399             il.MarkLabel(loop);
400             // fieldNames[index] 
401             il.Emit(OpCodes.Ldloc_2);
402             il.Emit(OpCodes.Ldloc_1);
403 
404             // = IDataRecord.GetName(index)
405             il.Emit(OpCodes.Ldarg_0);
406             il.Emit(OpCodes.Ldloc_1);
407             il.Emit(OpCodes.Callvirt, Method.DataRecord_GetName);
408             il.Emit(OpCodes.Stelem_Ref);
409 
410             // index  ;
411             il.Emit(OpCodes.Ldloc_1);
412             il.Emit(OpCodes.Ldc_I4_1);
413             il.Emit(OpCodes.Add);
414             il.Emit(OpCodes.Stloc_1);
415 
416             // if(index < fieldCount) { loop
417             il.Emit(OpCodes.Ldloc_1);
418             il.Emit(OpCodes.Ldarg_1);
419             il.Emit(OpCodes.Clt);
420             il.Emit(OpCodes.Brtrue, loop);
421 
422             #endregion
423 
424             #region  for (int index = 0; index < count; index  ) { item.xx = reader[index] 
425             for (int index = 0, count = columns.Count; index < count; index  )
426             {
427                 Label jump      = il.DefineLabel();
428                 DbColumn column = columns[index];
429 
430                 // index = IndexOf(fieldCount, fieldNames, name)
431                 il.Emit(OpCodes.Ldarg_1); // fieldCount
432                 il.Emit(OpCodes.Ldloc_2); // fieldNames
433                 il.Emit(OpCodes.Ldstr, column.Name);
434                 il.Emit(OpCodes.Call,  Method.String_IndexOf);
435                 il.Emit(OpCodes.Stloc_1);
436 
437                 // if(index == -1) => go jump
438                 il.Emit(OpCodes.Ldloc_1);
439                 il.Emit(OpCodes.Ldc_I4_M1);
440                 il.Emit(OpCodes.Ceq);
441                 il.Emit(OpCodes.Brtrue, jump);
442 
443                 // t.xx = MyConvert.ToXXXX(dr[index])
444                 il.Emit(OpCodes.Ldloc_0); // t
445                 il.Emit(OpCodes.Ldarg_0); // reader
446                 il.Emit(OpCodes.Ldloc_1); 
447                 il.Emit(OpCodes.Callvirt, Method.DataRecord_GetValue);
448                 if(column.DataType != MyType.Object)
449                 {
450                     il.Emit(OpCodes.Call, column.ConvertMethod);
451                 }
452                 il.Emit(OpCodes.Callvirt, column.SetMethod);
453                 il.MarkLabel(jump);
454             }
455 
456             #endregion
457         }  
458        #endregion
459 
460     }
461 }

  DataTable 转 List 测量试验结果图(只测量检验转实体消耗的时间,数据量:419,196):

View Code

4、DbColumnAttribute

 1 using System;
 2 using System.Data;
 3 
 4 namespace Model
 5 {
 6     public class User2
 7     {
 8         public string uid { get; set; }
 9 
10         public string mobile { get; set; }
11 
12         public string realname { get; set; }
13 
14         public DateTime? regTime { get; set; }
15 
16         public string orig_src { get; set; }
17 
18         public string referrerid { get; set; }
19 
20         public string referrername { get; set; } 
21 
22     }
23 
24     public static class UserFactory
25     {
26         public static User2 GetUser(DataRow dr)
27         {
28             return new User2()
29             {
30                 uid          = dr[0] as string,
31                 mobile       = dr[1] as string,
32                 realname     = dr[2] as string,
33                 regTime      = (DateTime)dr[3],
34                 orig_src     = dr[4] as string,
35                 referrerid   = dr[5] as string,
36                 referrername = dr[6] as string
37             };
38         }
39     }
40 }

  时时app平台注册网站 17

View Code

View Code

6、Method.cs

时时app平台注册网站 18时时app平台注册网站 19

 1 using System;
 2 
 3 namespace Mapper
 4 {
 5     public class DbColumnAttribute : Attribute
 6     {
 7         public DbColumnAttribute()
 8         {
 9         }
10 
11         public string Name { get; set; }
12     }
13 }

  网络关于Emit生成实体的篇章也是超过一半牛毛,亦犹如Dapper类的开源框架,重复造轮子,也只是为着知其所以然。笔者个人还是相比侧向于写原生SQL,成熟的ORM不在少数,但风姿浪漫碰上由多规格、多表组成的分页数据,ORM生成的SQL很难称心如意。直接用DataTable或DataReader可读性又差,一个个类手写映射代码,耗时困难还易于失误。于是,只好入手弄个转变器,固然功用赶不上手写代码,但从结果来看,平常使用基本没啥难题。

  相关代码:

1、实体类

时时app平台注册网站 20时时app平台注册网站 21

 1 namespace Mapper
 2 {
 3     public class MyType
 4     {
 5         public static readonly System.Type
 6             Nullable               = typeof(System.Nullable),
 7             Enum                   = typeof(System.Enum),
 8             Object                 = typeof(object),
 9             Byte                   = typeof(byte),
10             SByte                  = typeof(sbyte), 
11             Int16                  = typeof(short),
12             UInt16                 = typeof(ushort),
13             Int32                  = typeof(int),
14             UInt32                 = typeof(uint),
15             Int64                  = typeof(long),
16             UInt64                 = typeof(ulong),
17             Single                 = typeof(float),
18             Decimal                = typeof(decimal),
19             Double                 = typeof(double),
20             Boolean                = typeof(bool),
21             Char                   = typeof(char),
22             String                 = typeof(string),
23             Guid                   = typeof(System.Guid),
24             DateTime               = typeof(System.DateTime),
25             DateTimeOffset         = typeof(System.DateTimeOffset),
26             NullableByte           = typeof(byte?),
27             NullableSByte          = typeof(sbyte?),
28             NullableInt16          = typeof(short?),
29             NullableUInt16         = typeof(ushort?),
30             NullableInt32          = typeof(int?),
31             NullableUInt32         = typeof(uint?),
32             NullableInt64          = typeof(long?),
33             NullableUInt64         = typeof(ulong?),
34             NullableSingle         = typeof(float?),
35             NullableDecimal        = typeof(decimal?),
36             NullableDouble         = typeof(double?),
37             NullableBoolean        = typeof(bool?),
38             NullableChar           = typeof(char?),
39             NullableGuid           = typeof(System.Guid?),
40             NullableDateTime       = typeof(System.DateTime?),
41             NullableDateTimeOffset = typeof(System.DateTimeOffset?),
42             ByteArray              = typeof(byte[]),
43             IntArray               = typeof(int[]),
44             StringArray            = typeof(string[]),                                 
45             Exception              = typeof(System.Exception),
46             Convert                = typeof(System.Convert),
47             IEnumerator            = typeof(System.Collections.IEnumerator),                                  
48             MyConvert              = typeof(MyConvert),                                  
49             DbColumn               = typeof(DbColumnAttribute),
50             DataRow                = typeof(System.Data.DataRow),
51             DataRows               = typeof(System.Data.DataRowCollection),
52             DataTable              = typeof(System.Data.DataTable),
53             DataColumns            = typeof(System.Data.DataColumnCollection),
54             IDataRecord            = typeof(System.Data.IDataRecord),
55             IDataReader            = typeof(System.Data.IDataReader);
56 
57         public static readonly System.Type[]
58             ArrayObject            = new System.Type[] { Object },
59             ArrayInt               = new System.Type[] { Int32 },
60             ArrayString            = new System.Type[] { String };
61     }
62 }

5、TypeHelper.cs

View Code

View Code

  1 using System;
  2 using System.Data;
  3 using System.Reflection;
  4 using System.Reflection.Emit;
  5 using System.Collections.Generic;
  6 using System.Collections.Concurrent;
  7 
  8 namespace Mapper
  9 {
 10     public class MyDataTable<T>
 11     {
 12 
 13         #region 变量
 14         private delegate List<T> ListHandler(DataTable table, int rows);
 15 
 16         private delegate T SingleHandler(DataTable table);
 17 
 18         private const int MAX_CACHE_COUNT = 10000;
 19 
 20         private static readonly Type
 21             typeToSingle = typeof(SingleHandler),
 22             typeToList   = typeof(ListHandler);
 23 
 24         private static readonly ConcurrentDictionary<string, SingleHandler>
 25             dictSingle   = new ConcurrentDictionary<string, SingleHandler>(StringComparer.OrdinalIgnoreCase);
 26 
 27         private static readonly ConcurrentDictionary<string, ListHandler>
 28             dictList     = new ConcurrentDictionary<string, ListHandler>(StringComparer.OrdinalIgnoreCase);
 29         #endregion
 30 
 31         #region ToList
 32         public static List<T> ToList(DataTable table)
 33         {
 34             int rows = null == table ? 0 : table.Rows.Count   1;
 35             if (1 < rows)
 36             {
 37                 try
 38                 {
 39                     Type type   = typeof(T);
 40                     string key  = type.FullName;
 41                     ListHandler handler;
 42                     dictList.TryGetValue(key, out handler);
 43                     if (null != handler)
 44                     {
 45                         return handler(table, rows);
 46                     }
 47                     if (dictList.Count > MAX_CACHE_COUNT)
 48                     {
 49                         dictList.Clear();
 50                     }
 51                     handler = GetListHandler(type, key);
 52                     if (null != handler)
 53                     {
 54                         return handler(table, rows);
 55                     }                  
 56                 }
 57                 catch (Exception ex)
 58                 {
 59                     #if DEBUG
 60                     throw ex;
 61                     #endif
 62                     // Log.XXX(ex);
 63                 }
 64             }
 65             return null;
 66         }
 67 
 68         private static ListHandler GetListHandler(Type type, string key)
 69         {
 70             Type typeList               = typeof(List<T>);
 71             DynamicMethod method        = new DynamicMethod(string.Empty, typeList, new Type[] { MyType.DataTable, MyType.Int32 }, true);
 72             ILGenerator il              = method.GetILGenerator();
 73             // List<T> list = new List<T>(rows);
 74             il.DeclareLocal(typeList);
 75             il.Emit(OpCodes.Ldarg_1);
 76             il.Emit(OpCodes.Newobj, typeList.GetConstructor(MyType.ArrayInt));
 77             il.Emit(OpCodes.Stloc_0);
 78             Bind(il, typeList, type);
 79             // return list
 80             il.Emit(OpCodes.Ldloc_0);
 81             il.Emit(OpCodes.Ret);
 82             ListHandler Handler = method.CreateDelegate(typeToList) as ListHandler;
 83             dictList[key]     = Handler;
 84             return Handler;
 85         }
 86 
 87         private static void Bind(ILGenerator il,Type list, Type item)
 88         {
 89             if (item.IsValueType)
 90             {
 91                 if (item.IsEnum)
 92                 {
 93                     item = Enum.GetUnderlyingType(item);
 94                 }
 95                 else if (string.Equals(item.Name, "Nullable`1"))
 96                 {
 97                     Type temp = Nullable.GetUnderlyingType(item);
 98                     if (temp.IsEnum)
 99                     {
100                         item = TypeHelper.GetNullableEnum(Enum.GetUnderlyingType(temp));
101                     }
102                 }
103                 BindOther(il, item, list.GetMethod("Add"));
104             }
105             else if (item == MyType.String)
106             {
107                 BindOther(il, item, list.GetMethod("Add"));
108             }
109             else if (item == MyType.Object)
110             {
111                 BindOther(il, item, list.GetMethod("Add"), false);
112             }
113             else
114             {
115                 ConstructorInfo constructor = item.GetConstructor(Type.EmptyTypes);
116                 if (null != constructor)
117                 {
118                     BindClass(il, item, list.GetMethod("Add"), constructor);
119                 }
120             }
121         }
122 
123         private static void BindClass(ILGenerator il, Type type, MethodInfo add, ConstructorInfo constructor)
124         {
125             List<DbColumn> columns  = TypeHelper.GetCanSetColumns(type);
126             int count               =  columns.Count;
127             Label loop              = il.DefineLabel();
128             Label exit              = il.DefineLabel();
129             //T t -> 索引1
130             il.DeclareLocal(type);
131             //IEnumerator enumerator = DataTable.Rows.GetEnumerator(); -> 索引2
132             il.DeclareLocal(MyType.IEnumerator);
133             il.Emit(OpCodes.Ldarg_0);
134             il.Emit(OpCodes.Callvirt, Method.DataTable_GetRows);
135             il.Emit(OpCodes.Callvirt, Method.Rows_GetEnumerator);
136             il.Emit(OpCodes.Stloc_2);
137             // DataRow row; -> 索引3
138             il.DeclareLocal(MyType.DataRow);
139             // 获取列索引
140             GetColumnIndices(il, columns, count);
141             // while (reader.Read()) {
142             il.MarkLabel(loop);
143             il.Emit(OpCodes.Ldloc_2);
144             il.Emit(OpCodes.Callvirt,  Method.IEnumerator_MoveNext);
145             il.Emit(OpCodes.Brfalse,   exit);
146             // row = enumerator.Current as DataRow;
147             il.Emit(OpCodes.Ldloc_2);
148             il.Emit(OpCodes.Callvirt,  Method.IEnumerator_Current);
149             il.Emit(OpCodes.Castclass, MyType.DataRow);
150             il.Emit(OpCodes.Stloc_3);
151             BuildItem(il, columns, type, count, constructor);
152             // list.Add(t);
153             il.Emit(OpCodes.Ldloc_0);
154             il.Emit(OpCodes.Ldloc_1);
155             il.Emit(OpCodes.Callvirt, add);
156             il.Emit(OpCodes.Br,       loop);
157             // }
158             il.MarkLabel(exit);
159         }
160 
161         private static void BindOther(ILGenerator il, Type type, MethodInfo add, bool needConvert = true)
162         {
163             MethodInfo convertMethod = null;
164             if (needConvert)
165             {
166                 convertMethod = Method.Get(type);
167                 if (null == convertMethod)
168                 {
169                     return;
170                 }
171             }
172             Label loop = il.DefineLabel();
173             Label exit = il.DefineLabel();
174             //IEnumerator enumerator = DataTable.Rows.GetEnumerator(); -> 索引1
175             il.DeclareLocal(MyType.IEnumerator);
176             il.Emit(OpCodes.Ldarg_0);
177             il.Emit(OpCodes.Callvirt, Method.DataTable_GetRows);
178             il.Emit(OpCodes.Callvirt, Method.Rows_GetEnumerator);
179             il.Emit(OpCodes.Stloc_1);
180             // DataRow row; -> 索引2
181             il.DeclareLocal(MyType.DataRow);
182             // while (enumerator.MoveNext()) {
183             il.MarkLabel(loop);
184             il.Emit(OpCodes.Ldloc_1);
185             il.Emit(OpCodes.Callvirt,  Method.IEnumerator_MoveNext);
186             il.Emit(OpCodes.Brfalse,   exit);
187             // row = enumerator.Current as DataRow;
188             il.Emit(OpCodes.Ldloc_1);
189             il.Emit(OpCodes.Callvirt,  Method.IEnumerator_Current);
190             il.Emit(OpCodes.Castclass, MyType.DataRow);
191             il.Emit(OpCodes.Stloc_2);
192             //list.Add(MyConvert.ToXXX(dr.Getvalue(0)));
193             il.Emit(OpCodes.Ldloc_0);  // list
194             il.Emit(OpCodes.Ldloc_2);  // row -> DataRow
195             il.Emit(OpCodes.Ldc_I4_0);
196             il.Emit(OpCodes.Callvirt,  Method.DataRow_GetItem);
197             if (needConvert)
198             {
199                 il.Emit(OpCodes.Call,  convertMethod);
200             }
201             il.Emit(OpCodes.Callvirt,  add);
202             il.Emit(OpCodes.Br,        loop);
203             // }
204             il.MarkLabel(exit);
205         }
206 
207         private static void GetColumnIndices(ILGenerator il, List<DbColumn> columns, int count)
208         {
209             // DataColumnCollection colums = DataTable.Columns; -> 索引4
210             il.DeclareLocal(MyType.DataColumns);
211             il.Emit(OpCodes.Ldarg_0);
212             il.Emit(OpCodes.Callvirt, Method.DataTable_Columns);
213             il.Emit(OpCodes.Stloc,    4);
214             for (int index = 0; index < count; index  )
215             {
216                 il.DeclareLocal(MyType.Int32);
217                 il.Emit(OpCodes.Ldloc,    4);
218                 il.Emit(OpCodes.Ldstr,    columns[index].Name);
219                 il.Emit(OpCodes.Callvirt, Method.DataColumns_IndexOf);
220                 il.Emit(OpCodes.Stloc,    index 5);
221             }
222             // return result;
223         }
224 
225         private static void BuildItem(ILGenerator il, List<DbColumn> columns, Type type, int count, ConstructorInfo constructor)
226         {
227             il.Emit(OpCodes.Newobj, constructor);
228             il.Emit(OpCodes.Stloc_1);
229             for (int index = 0; index < count; index  )
230             {
231                 Label next      = il.DefineLabel();
232                 DbColumn column = columns[index];           
233                 // if(columnIndex == -1) { jump => next
234                 il.Emit(OpCodes.Ldloc,    index 5);
235                 il.Emit(OpCodes.Ldc_I4_M1);
236                 il.Emit(OpCodes.Ceq);
237                 il.Emit(OpCodes.Brtrue, next);
238 
239                 // item.xxx = dr[index]
240                 il.Emit(OpCodes.Ldloc_1);   // t   -> T
241                 il.Emit(OpCodes.Ldloc, 3);  // row -> DataRow
242                 il.Emit(OpCodes.Ldloc, index   5);
243                 il.Emit(OpCodes.Callvirt, Method.DataRow_GetItem);
244                 if (column.DataType != MyType.Object)
245                 {
246                     il.Emit(OpCodes.Call, column.ConvertMethod);
247                 }
248                 il.Emit(OpCodes.Callvirt, column.SetMethod);
249                 il.MarkLabel(next);
250             }
251         }
252         #endregion
253 
254         #region ToSingle
255         public static T ToSingle(DataTable table)
256         {
257             if (null != table)
258             {
259                 try
260                 {
261                     Type type   = typeof(T);
262                     string key  = type.FullName;
263                     SingleHandler handler;
264                     dictSingle.TryGetValue(key, out handler);
265                     if (null != handler)
266                     {
267                         return handler(table);
268                     }
269                     if (dictSingle.Count > MAX_CACHE_COUNT)
270                     {
271                         dictSingle.Clear();
272                     }
273                     handler = GetSingleHandler(type, key);
274                     if (null != handler)
275                     {
276                         return handler(table);
277                     }  
278                 }
279                 catch(Exception ex)
280                 {
281                     #if DEBUG
282                     throw ex;
283                     #endif
284                     // Log.XXX(ex);
285                 }
286             }
287             return default(T);
288         }
289 
290         private static SingleHandler GetSingleHandler(Type type, string key)
291         {
292             DynamicMethod method = new DynamicMethod(string.Empty, type, new Type[] { MyType.DataTable }, true);
293             ILGenerator il       = method.GetILGenerator();
294             Label exit           = il.DefineLabel();
295             // T t
296             il.DeclareLocal(type);
297             // IEnumerator enumerator = DataTable.Rows.GetEnumerator();
298             il.DeclareLocal(MyType.IEnumerator);
299             il.Emit(OpCodes.Ldarg_0);
300             il.Emit(OpCodes.Callvirt, Method.DataTable_GetRows);
301             il.Emit(OpCodes.Callvirt, Method.Rows_GetEnumerator);
302             il.Emit(OpCodes.Stloc_1);
303             // if (enumerator.MoveNext()) {
304             il.Emit(OpCodes.Ldloc_1);
305             il.Emit(OpCodes.Callvirt, Method.IEnumerator_MoveNext);
306             il.Emit(OpCodes.Brfalse, exit);
307             // DataRow row = enumerator.Current as DataRow;
308             il.DeclareLocal(MyType.DataRow);
309             il.Emit(OpCodes.Ldloc_1);
310             il.Emit(OpCodes.Callvirt, Method.IEnumerator_Current);
311             il.Emit(OpCodes.Castclass, MyType.DataRow);
312             il.Emit(OpCodes.Stloc_2);
313             Bind(il, type);
314             il.MarkLabel(exit);
315             il.Emit(OpCodes.Ldloc_0);
316             il.Emit(OpCodes.Ret);
317             SingleHandler Handler = method.CreateDelegate(typeToSingle) as SingleHandler;
318             dictSingle[key] = Handler;
319             return Handler;
320         }
321 
322         public static void Bind(ILGenerator il, Type type)
323         {
324             if (type.IsValueType)
325             {
326                 if (type.IsEnum)
327                 {
328                     type = Enum.GetUnderlyingType(type);
329                 }
330                 else if (string.Equals(type.Name, "Nullable`1"))
331                 {
332                     Type tempType = Nullable.GetUnderlyingType(type);
333                     if (tempType.IsEnum)
334                     {
335                         type = TypeHelper.GetNullableEnum(Enum.GetUnderlyingType(tempType));
336                     }
337                 }
338                 BindOther(il, type);
339             }
340             else if (type == MyType.String)
341             {
342                 BindOther(il, type);
343             }
344             else if (type == MyType.Object)
345             {
346                 BindOther(il, type, false);
347             }
348             else
349             {
350                 ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
351                 if (null != constructor)
352                 {
353                     BindClass(il, type, constructor);
354                 }
355             }
356         }
357 
358         public static void BindOther(ILGenerator il, Type type, bool needConvert = true)
359         {
360             MethodInfo convertMethod = null;
361             if (needConvert)
362             {
363                 convertMethod = Method.Get(type);
364                 if (null == convertMethod)
365                 {
366                     return;
367                 }
368             }
369             il.Emit(OpCodes.Ldloc_2);
370             il.Emit(OpCodes.Ldc_I4_0);
371             il.Emit(OpCodes.Call,     Method.DataRow_GetItem);
372             if (needConvert)
373             {
374                 il.Emit(OpCodes.Call, convertMethod);
375             }
376             il.Emit(OpCodes.Stloc_0);
377         }
378 
379         public static void BindClass(ILGenerator il, Type type, ConstructorInfo constructor)
380         {
381             List<DbColumn> columns = TypeHelper.GetCanSetColumns(type);
382             // t = new T()
383             il.Emit(OpCodes.Newobj, constructor);
384             il.Emit(OpCodes.Stloc_0);
385 
386             // DataColumnCollection columns = DataTable.Columns;
387             il.DeclareLocal(MyType.DataColumns);
388             il.Emit(OpCodes.Ldarg_0);
389             il.Emit(OpCodes.Callvirt, Method.DataTable_Columns);
390             il.Emit(OpCodes.Stloc_3);
391 
392             // int columnIndex;
393             il.DeclareLocal(MyType.Int32);
394 
395             for (int index = 0, count = columns.Count; index < count; index  )
396             {
397                 Label next      = il.DefineLabel();
398                 DbColumn column = columns[index];
399                 // columnIndex = columns.IndexOf(columnName)
400                 il.Emit(OpCodes.Ldloc_3);
401                 il.Emit(OpCodes.Ldstr,    columns[index].Name);
402                 il.Emit(OpCodes.Callvirt, Method.DataColumns_IndexOf);
403                 il.Emit(OpCodes.Stloc,    4);
404                 // if(columnIndex == -1) { jump => next
405                 il.Emit(OpCodes.Ldloc, 4);
406                 il.Emit(OpCodes.Ldc_I4_M1);
407                 il.Emit(OpCodes.Ceq);
408                 il.Emit(OpCodes.Brtrue, next);
409                 // item.xxx = row[columnIndex]
410                 il.Emit(OpCodes.Ldloc_0);
411                 il.Emit(OpCodes.Ldloc_2);
412                 il.Emit(OpCodes.Ldloc,    4);
413                 il.Emit(OpCodes.Callvirt, Method.DataRow_GetItem);
414                 if (column.DataType != MyType.Object)
415                 {
416                     il.Emit(OpCodes.Call, column.ConvertMethod);
417                 }
418                 il.Emit(OpCodes.Callvirt, column.SetMethod);
419                 il.MarkLabel(next);
420             }        
421         }
422         #endregion
423 
424     }
425 }

3、DbColumn.cs 

View Code

 

View Code

  1 using System;
  2 using System.Reflection;
  3 
  4 namespace Mapper
  5 {
  6     internal static class Method
  7     {
  8 
  9         #region 变量
 10         internal static readonly MethodInfo
 11             ToObject                 = MyType.MyConvert.GetMethod("ToObject",                 MyType.ArrayObject),              
 12             ToByte                   = MyType.MyConvert.GetMethod("ToByte",                   MyType.ArrayObject),
 13             ToSByte                  = MyType.MyConvert.GetMethod("ToSByte",                  MyType.ArrayObject),
 14             ToByteArray              = MyType.MyConvert.GetMethod("ToByteArray",              MyType.ArrayObject),
 15             ToInt16                  = MyType.MyConvert.GetMethod("ToInt16",                  MyType.ArrayObject),
 16             ToUInt16                 = MyType.MyConvert.GetMethod("ToUInt16",                 MyType.ArrayObject),
 17             ToInt32                  = MyType.MyConvert.GetMethod("ToInt32",                  MyType.ArrayObject),
 18             ToUInt32                 = MyType.MyConvert.GetMethod("ToUInt32",                 MyType.ArrayObject),
 19             ToInt64                  = MyType.MyConvert.GetMethod("ToInt64",                  MyType.ArrayObject),
 20             ToUInt64                 = MyType.MyConvert.GetMethod("ToUInt64",                 MyType.ArrayObject),
 21             ToSingle                 = MyType.MyConvert.GetMethod("ToSingle",                 MyType.ArrayObject),
 22             ToDecimal                = MyType.MyConvert.GetMethod("ToDecimal",                MyType.ArrayObject),
 23             ToDouble                 = MyType.MyConvert.GetMethod("ToDouble",                 MyType.ArrayObject),
 24             ToBoolean                = MyType.MyConvert.GetMethod("ToBoolean",                MyType.ArrayObject),
 25             ToDateTime               = MyType.MyConvert.GetMethod("ToDateTime",               MyType.ArrayObject),
 26             ToDateTimeOffset         = MyType.MyConvert.GetMethod("ToDateTimeOffset",         MyType.ArrayObject),
 27             ToChar                   = MyType.MyConvert.GetMethod("ToChar",                   MyType.ArrayObject),
 28             ToStr                    = MyType.Convert.GetMethod("ToString",                   MyType.ArrayObject),
 29             ToGuid                   = MyType.MyConvert.GetMethod("ToGuid",                   MyType.ArrayObject),
 30             ToNullableByte           = MyType.MyConvert.GetMethod("ToByteNullable",           MyType.ArrayObject),
 31             ToNullableSByte          = MyType.MyConvert.GetMethod("ToSByteNullable",          MyType.ArrayObject),
 32             ToNullableInt16          = MyType.MyConvert.GetMethod("ToInt16Nullable",          MyType.ArrayObject),
 33             ToNullableUInt16         = MyType.MyConvert.GetMethod("ToUInt16Nullable",         MyType.ArrayObject),
 34             ToNullableInt32          = MyType.MyConvert.GetMethod("ToInt32Nullable",          MyType.ArrayObject),
 35             ToNullableUInt32         = MyType.MyConvert.GetMethod("ToUInt32Nullable",         MyType.ArrayObject),
 36             ToNullableInt64          = MyType.MyConvert.GetMethod("ToInt64Nullable",          MyType.ArrayObject),
 37             ToNullableUInt64         = MyType.MyConvert.GetMethod("ToUInt64Nullable",         MyType.ArrayObject),
 38             ToNullableSingle         = MyType.MyConvert.GetMethod("ToSingleNullable",         MyType.ArrayObject),
 39             ToNullableDecimal        = MyType.MyConvert.GetMethod("ToDecimalNullable",        MyType.ArrayObject),
 40             ToNullableDouble         = MyType.MyConvert.GetMethod("ToDoubleNullable",         MyType.ArrayObject),
 41             ToNullableBoolean        = MyType.MyConvert.GetMethod("ToBooleanNullable",        MyType.ArrayObject),
 42             ToNullableDateTime       = MyType.MyConvert.GetMethod("ToDateTimeNullable",       MyType.ArrayObject),
 43             ToNullableDateTimeOffset = MyType.MyConvert.GetMethod("ToDateTimeOffsetNullable", MyType.ArrayObject),
 44             ToNullableChar           = MyType.MyConvert.GetMethod("ToCharNullable",           MyType.ArrayObject),
 45             ToNullableGuid           = MyType.MyConvert.GetMethod("ToGuidNullable",           MyType.ArrayObject),
 46             String_IndexOf           = MyType.MyConvert.GetMethod("IndexOf",                  new Type[] { MyType.Int32, MyType.StringArray, MyType.String }),
 47             
 48             DataReader_Read          = MyType.IDataReader.GetMethod("Read"),
 49             DataRecord_GetValue      = MyType.IDataRecord.GetMethod("GetValue",               MyType.ArrayInt),
 50             DataRecord_GetName       = MyType.IDataRecord.GetMethod("GetName",                MyType.ArrayInt),
 51                                                                                               
 52             DataRow_GetItem          = MyType.DataRow.GetMethod("get_Item",                   MyType.ArrayInt),
 53             Rows_GetEnumerator       = MyType.DataRows.GetMethod("GetEnumerator"),            
 54                                                                                               
 55             DataColumns_IndexOf      = MyType.DataColumns.GetMethod("IndexOf",                MyType.ArrayString),
 56             DataColumns_Contains     = MyType.DataColumns.GetMethod("Contains"),
 57                                      
 58             DataTable_GetRows        = MyType.DataTable.GetMethod("get_Rows"),
 59             DataTable_Columns        = MyType.DataTable.GetMethod("get_Columns"),
 60                                      
 61             IEnumerator_MoveNext     = MyType.IEnumerator.GetMethod("MoveNext"),
 62             IEnumerator_Current      = MyType.IEnumerator.GetMethod("get_Current");
 63         #endregion
 64 
 65         #region Get
 66         public static MethodInfo Get(Type type)
 67         {
 68             if(type == MyType.String)
 69             {
 70                 return ToStr;
 71             }
 72 
 73             if(type == MyType.Int32)
 74             {
 75                 return ToInt32;
 76             }
 77 
 78             if (type == MyType.Int64)
 79             {
 80                 return ToInt64;
 81             }
 82 
 83             if(type == MyType.Decimal)
 84             {
 85                 return ToDecimal;
 86             }
 87 
 88             if (type == MyType.DateTime)
 89             {
 90                 return ToDateTime;
 91             }
 92 
 93             if (type == MyType.NullableDateTime)
 94             {
 95                 return ToNullableDateTime;
 96             }
 97 
 98             if(type == MyType.Boolean)
 99             {
100                 return ToBoolean;
101             }
102 
103             if (type == MyType.Double)
104             {
105                 return ToDouble;
106             }
107 
108             if (type == MyType.Single)
109             {
110                 return ToSingle;
111             }
112 
113             if(type == MyType.Int16)
114             {
115                 return ToInt16;
116             }
117 
118             if (type == MyType.UInt16)
119             {
120                 return ToUInt16;
121             }
122 
123             if (type == MyType.UInt32)
124             {
125                 return ToUInt32;
126             }
127 
128             if (type == MyType.UInt64)
129             {
130                 return ToUInt64;
131             }
132 
133             if(type == MyType.Byte)
134             {
135                 return ToByte;
136             }
137 
138             if (type == MyType.SByte)
139             {
140                 return ToSByte;
141             }
142 
143             if (type == MyType.ByteArray)
144             {
145                 return ToByteArray;
146             }
147 
148             if (type == MyType.Char)
149             {
150                 return ToChar;
151             }
152 
153             if(type == MyType.Guid)
154             {
155                 return ToGuid;
156             }
157 
158             if(type == MyType.NullableByte)
159             {
160                 return ToNullableByte;
161             }
162             if (type == MyType.NullableSByte)
163             {
164                 return ToNullableSByte;
165             }
166 
167             if(type == MyType.NullableInt16)
168             {
169                 return ToNullableInt16;
170             }
171             if (type == MyType.NullableUInt16)
172             {
173                 return ToNullableUInt16;
174             }
175 
176             if (type == MyType.NullableInt32)
177             {
178                 return ToNullableInt32;
179             }
180             if (type == MyType.NullableUInt32)
181             {
182                 return ToNullableUInt32;
183             }
184 
185             if (type == MyType.NullableInt64)
186             {
187                 return ToNullableInt64;
188             }
189             if (type == MyType.NullableUInt64)
190             {
191                 return ToNullableUInt64;
192             }
193 
194             if(type == MyType.NullableDecimal)
195             {
196                 return ToNullableDecimal;
197             }
198 
199             if (type == MyType.NullableDouble)
200             {
201                 return ToNullableDouble;
202             }
203 
204             if (type == MyType.NullableSingle)
205             {
206                 return ToNullableSingle;
207             }
208 
209             if(type == MyType.NullableBoolean)
210             {
211                 return ToNullableBoolean;
212             }
213 
214             if (type == MyType.NullableChar)
215             {
216                 return ToNullableChar;
217             }
218 
219             if (type == MyType.NullableGuid)
220             {
221                 return ToNullableGuid;
222             }
223 
224             if(type == MyType.DateTimeOffset)
225             {
226                 return ToDateTimeOffset;
227             }
228 
229             if (type == MyType.NullableDateTimeOffset)
230             {
231                 return ToNullableDateTimeOffset;
232             }
233             
234             if(type == MyType.Object)
235             {
236                 return ToObject;
237             }
238 
239             return null;
240         }
241         #endregion
242     }
243 }

本文由时时app平台注册网站发布于编程知识,转载请注明出处:收获分享(-) — 利用Emit生成实体【时时app平台

关键词: