程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 果實分享(-) — 利用Emit生成實體,emit實體

果實分享(-) — 利用Emit生成實體,emit實體

編輯:C#入門知識

果實分享(-) — 利用Emit生成實體,emit實體


  第一次寫博客,也不知該寫點什麼好,不如把最近鼓搗的成果分享一下,獨樂樂不如眾樂樂!

  Emit,就像個調皮的娃娃,難調教。初時,一個頭兩個大,後面才發現這貨吃硬不吃軟,只能是手寫等效C#代碼,然後模仿生成的IL代碼,雖然過程有點曲折,但娃娃不聽話,終究需要教育引導。

  網上關於Emit生成實體的文章也是多數牛毛,亦有如Dapper類的開源框架,重復造輪子,也只是為了知其所以然。我個人還是比較偏向於寫原生SQL,成熟的ORM不在少數,但一碰上由多條件、多表組成的分頁數據,ORM生成的SQL很難盡如人意。直接用DataTable或DataReader可讀性又差,一個個類手寫映射代碼,耗時費力還容易出錯。於是,只能動手弄個轉換器,雖然效率趕不上手寫代碼,但從結果來看,日常使用基本沒啥問題。

  DataTable 轉 List 測試結果圖(只測試轉實體消耗的時間,數據量:419,196):

  

 

  測試代碼:

1、實體類

 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 }
View Code

2、測試方法

 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         }
View Code

 

  相關代碼:

1、MyType.cs

 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 }
View Code

2、MyConvert.cs

  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 }
View Code

3、DbColumn.cs 

 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 }
View Code

4、DbColumnAttribute

 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 }
View Code

5、TypeHelper.cs

 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 }
View Code

6、Method.cs

  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 }
View Code

7、MyDataReader.cs

  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 SingleHander(IDataReader dr, int fieldCount);
 16 
 17         private delegate List<T> ListHander(IDataReader dr, int fieldCount);
 18 
 19         private const int MAX_CACHE_COUNT = 10000;
 20 
 21         private static readonly Type
 22             typeToSingle = typeof(SingleHander),
 23             typeToList   = typeof(ListHander);
 24        
 25         private static readonly ConcurrentDictionary<string, SingleHander> 
 26             dictSingle   = new ConcurrentDictionary<string, SingleHander>(StringComparer.OrdinalIgnoreCase);
 27 
 28         private static readonly ConcurrentDictionary<string, ListHander> 
 29             dictList     = new ConcurrentDictionary<string, ListHander>(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                     ListHander hander;
 44                     dictList.TryGetValue(key, out hander);
 45                     if (null != hander)
 46                     {
 47                         return hander(reader, cols);
 48                     }
 49                     if (dictList.Count > MAX_CACHE_COUNT)
 50                     {
 51                         dictList.Clear();
 52                     }
 53                     hander = GetListHander(type, key);
 54                     if (null != hander)
 55                     {
 56                         return hander(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 ListHander GetListHander(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             ListHander hander = method.CreateDelegate(typeToList) as ListHander;
 85             dictList[key]     = hander;
 86             return hander;
 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 
263         public static T ToSingle(IDataReader reader)
264         {
265             int cols = null == reader ? 0 : reader.FieldCount;
266             if (0 < cols)
267             {
268                 try
269                 {
270                     Type type  = typeof(T);
271                     string key = type.FullName;
272                     SingleHander hadner;
273                     dictSingle.TryGetValue(key, out hadner);
274                     if (null != hadner)
275                     {
276                         return hadner(reader, cols);
277                     }
278                     if (dictSingle.Count > MAX_CACHE_COUNT)
279                     {
280                         dictSingle.Clear();
281                     }
282                     hadner = GetSingleHander(type, key);
283                     if (null != hadner)
284                     {
285                         return hadner(reader, cols);
286                     }
287                 }
288                 catch (Exception ex)
289                 {
290                     #if DEBUG
291                        throw ex;
292                     #endif 
293                        // Log.XXX(ex);
294                 }
295             }
296             return default(T);
297         }
298 
299         private static SingleHander GetSingleHander(Type type, string key)
300         {
301             DynamicMethod method = new DynamicMethod(string.Empty, type, new Type[] { MyType.IDataReader, MyType.Int32 }, true);
302             ILGenerator il       = method.GetILGenerator();
303             Label exit           = il.DefineLabel();
304             // T t
305             il.DeclareLocal(type);
306             // if (reader.Read()) {
307             il.Emit(OpCodes.Ldarg_0);
308             il.Emit(OpCodes.Callvirt, Method.DataReader_Read);
309             il.Emit(OpCodes.Brfalse, exit);
310             Bind(il, type);
311             // }
312             il.MarkLabel(exit);
313             // return 
314             il.Emit(OpCodes.Ldloc_0);
315             il.Emit(OpCodes.Ret);
316             SingleHander hander = method.CreateDelegate(typeToSingle) as SingleHander;
317             dictSingle[key]     = hander;
318             return hander;
319         }
320 
321         private static void Bind(ILGenerator il, Type type)
322         {
323             if (type.IsValueType)
324             {
325                 if (type.IsEnum)
326                 {
327                     type = Enum.GetUnderlyingType(type);
328                 }
329                 else if (string.Equals(type.Name, "Nullable`1"))
330                 {
331                     Type tempType = Nullable.GetUnderlyingType(type);
332                     if (tempType.IsEnum)
333                     {
334                         type = TypeHelper.GetNullableEnum(Enum.GetUnderlyingType(tempType));
335                     }
336                 }
337                 BindOther(il, type);
338             }
339             else if (type == MyType.String)
340             {
341                 BindOther(il, type);
342             }
343             else if (type == MyType.Object)
344             {
345                 BindOther(il, type, false);
346             }
347             else
348             {
349                 ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
350                 if (null != constructor)
351                 {
352                     BindClass(il, type, constructor);
353                 }
354             }
355         }
356 
357         private static void BindOther(ILGenerator il, Type type, bool needConvert = true)
358         {
359             MethodInfo convertMethod = null;
360             if (needConvert)
361             {
362                 convertMethod = Method.Get(type);
363                 if (null == convertMethod)
364                 {
365                     return;
366                 }
367             }
368             //t = MyConvert.ToXXX(dr.Getvalue(0));
369             il.Emit(OpCodes.Ldarg_0);
370             il.Emit(OpCodes.Ldc_I4_0);
371             il.Emit(OpCodes.Callvirt, Method.DataRecord_GetValue);
372             if (needConvert)
373             {
374                 il.Emit(OpCodes.Call, convertMethod);
375             }
376             il.Emit(OpCodes.Stloc_0);
377         }
378 
379         private static void BindClass(ILGenerator il, Type type, ConstructorInfo constructor)
380         {
381             List<DbColumn> columns = TypeHelper.GetCanSetColumns(type);       
382             // T item = new T()
383             il.Emit(OpCodes.Newobj, constructor);
384             il.Emit(OpCodes.Stloc_0);
385 
386             #region string[] fieldNames = new string[fieldCount]
387             // int index = 0; 變量index索引: 1
388             il.DeclareLocal(MyType.Int32);
389             il.Emit(OpCodes.Ldc_I4_0);
390             il.Emit(OpCodes.Stloc_1);
391 
392             // string[] fieldNames = new string[fieldCount]; 索引2
393             il.DeclareLocal(MyType.StringArray);
394             il.Emit(OpCodes.Ldarg_1);
395             il.Emit(OpCodes.Newarr, MyType.String);
396             il.Emit(OpCodes.Stloc_2);
397 
398             // for(; index < count; index++) {fieldNames[i] = IDataRecord.GetName(index);}
399             Label loop = il.DefineLabel();
400             il.MarkLabel(loop);
401             // fieldNames[index] 
402             il.Emit(OpCodes.Ldloc_2);
403             il.Emit(OpCodes.Ldloc_1);
404 
405             // = IDataRecord.GetName(index)
406             il.Emit(OpCodes.Ldarg_0);
407             il.Emit(OpCodes.Ldloc_1);
408             il.Emit(OpCodes.Callvirt, Method.DataRecord_GetName);
409             il.Emit(OpCodes.Stelem_Ref);
410 
411             // index++;
412             il.Emit(OpCodes.Ldloc_1);
413             il.Emit(OpCodes.Ldc_I4_1);
414             il.Emit(OpCodes.Add);
415             il.Emit(OpCodes.Stloc_1);
416 
417             // if(index < fieldCount) { loop
418             il.Emit(OpCodes.Ldloc_1);
419             il.Emit(OpCodes.Ldarg_1);
420             il.Emit(OpCodes.Clt);
421             il.Emit(OpCodes.Brtrue, loop);
422 
423             #endregion
424 
425             #region  for (int index = 0; index < count; index++) { item.xx = reader[index] 
426             for (int index = 0, count = columns.Count; index < count; index++)
427             {
428                 Label jump      = il.DefineLabel();
429                 DbColumn column = columns[index];
430 
431                 // index = IndexOf(fieldCount, fieldNames, name)
432                 il.Emit(OpCodes.Ldarg_1); // fieldCount
433                 il.Emit(OpCodes.Ldloc_2); // fieldNames
434                 il.Emit(OpCodes.Ldstr, column.Name);
435                 il.Emit(OpCodes.Call,  Method.String_IndexOf);
436                 il.Emit(OpCodes.Stloc_1);
437 
438                 // if(index == -1) => go jump
439                 il.Emit(OpCodes.Ldloc_1);
440                 il.Emit(OpCodes.Ldc_I4_M1);
441                 il.Emit(OpCodes.Ceq);
442                 il.Emit(OpCodes.Brtrue, jump);
443 
444                 // t.xx = MyConvert.ToXXXX(dr[index])
445                 il.Emit(OpCodes.Ldloc_0); // t
446                 il.Emit(OpCodes.Ldarg_0); // reader
447                 il.Emit(OpCodes.Ldloc_1); 
448                 il.Emit(OpCodes.Callvirt, Method.DataRecord_GetValue);
449                 if(column.DataType != MyType.Object)
450                 {
451                     il.Emit(OpCodes.Call, column.ConvertMethod);
452                 }
453                 il.Emit(OpCodes.Callvirt, column.SetMethod);
454                 il.MarkLabel(jump);
455             }
456 
457             #endregion
458         }  
459        #endregion
460 
461     }
462 }
View Code

8、MyDataTable.cs

  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> ListHander(DataTable table, int rows);
 15 
 16         private delegate T SingleHander(DataTable table);
 17 
 18         private const int MAX_CACHE_COUNT = 10000;
 19 
 20         private static readonly Type
 21             typeToSingle = typeof(SingleHander),
 22             typeToList   = typeof(ListHander);
 23 
 24         private static readonly ConcurrentDictionary<string, SingleHander>
 25             dictSingle   = new ConcurrentDictionary<string, SingleHander>(StringComparer.OrdinalIgnoreCase);
 26 
 27         private static readonly ConcurrentDictionary<string, ListHander>
 28             dictList     = new ConcurrentDictionary<string, ListHander>(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                     ListHander hander;
 42                     dictList.TryGetValue(key, out hander);
 43                     if (null != hander)
 44                     {
 45                         return hander(table, rows);
 46                     }
 47                     if (dictList.Count > MAX_CACHE_COUNT)
 48                     {
 49                         dictList.Clear();
 50                     }
 51                     hander = GetListHander(type, key);
 52                     if (null != hander)
 53                     {
 54                         return hander(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 ListHander GetListHander(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             ListHander hander = method.CreateDelegate(typeToList) as ListHander;
 83             dictList[key]     = hander;
 84             return hander;
 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                     SingleHander hander;
264                     dictSingle.TryGetValue(key, out hander);
265                     if (null != hander)
266                     {
267                         return hander(table);
268                     }
269                     if (dictSingle.Count > MAX_CACHE_COUNT)
270                     {
271                         dictSingle.Clear();
272                     }
273                     hander = GetSingleHander(type, key);
274                     if (null != hander)
275                     {
276                         return hander(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 SingleHander GetSingleHander(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             SingleHander hander = method.CreateDelegate(typeToSingle) as SingleHander;
318             dictSingle[key] = hander;
319             return hander;
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 }
View Code

  很多代碼,也是借鑒廣大網友分享的成果而來,在此表示感謝!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved