1
1

DataTableBuilder.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using System;
  2. using System.Data;
  3. using System.Reflection;
  4. using System.Reflection.Emit;
  5. namespace Masuit.Tools.Core.Database
  6. {
  7. internal class DataTableBuilder<T>
  8. {
  9. private static readonly MethodInfo GetValueMethod = typeof(DataRow).GetMethod("get_Item", new[]
  10. {
  11. typeof(int)
  12. });
  13. private static readonly MethodInfo IsDbNullMethod = typeof(DataRow).GetMethod("IsNull", new[]
  14. {
  15. typeof(int)
  16. });
  17. private delegate T Load(DataRow dataRecord);
  18. private Load _handler;
  19. private DataTableBuilder()
  20. {
  21. }
  22. public T Build(DataRow dataRecord)
  23. {
  24. return _handler(dataRecord);
  25. }
  26. public static DataTableBuilder<T> CreateBuilder(DataRow dataRecord)
  27. {
  28. DataTableBuilder<T> dynamicBuilder = new DataTableBuilder<T>();
  29. DynamicMethod method = new DynamicMethod("DynamicCreateEntity", typeof(T), new Type[]
  30. {
  31. typeof(DataRow)
  32. }, typeof(T), true);
  33. ILGenerator generator = method.GetILGenerator();
  34. LocalBuilder result = generator.DeclareLocal(typeof(T));
  35. generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
  36. generator.Emit(OpCodes.Stloc, result);
  37. for (int i = 0; i < dataRecord.ItemArray.Length; i++)
  38. {
  39. PropertyInfo propertyInfo = typeof(T).GetProperty(dataRecord.Table.Columns[i].ColumnName);
  40. Label endIfLabel = generator.DefineLabel();
  41. if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
  42. {
  43. generator.Emit(OpCodes.Ldarg_0);
  44. generator.Emit(OpCodes.Ldc_I4, i);
  45. generator.Emit(OpCodes.Callvirt, IsDbNullMethod);
  46. generator.Emit(OpCodes.Brtrue, endIfLabel);
  47. generator.Emit(OpCodes.Ldloc, result);
  48. generator.Emit(OpCodes.Ldarg_0);
  49. generator.Emit(OpCodes.Ldc_I4, i);
  50. generator.Emit(OpCodes.Callvirt, GetValueMethod);
  51. generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
  52. generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
  53. generator.MarkLabel(endIfLabel);
  54. }
  55. }
  56. generator.Emit(OpCodes.Ldloc, result);
  57. generator.Emit(OpCodes.Ret);
  58. dynamicBuilder._handler = (Load)method.CreateDelegate(typeof(Load));
  59. return dynamicBuilder;
  60. }
  61. }
  62. }