FastToT.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Reflection.Emit;
  5. using System.Reflection;
  6. using Ant.ORM.Table;
  7. namespace Ant.ORM.Tool
  8. {
  9. /// <summary>
  10. /// 快速转换类[数据量越大[500条起],性能越高]
  11. /// </summary>
  12. internal class FastToT<T>
  13. {
  14. public delegate T EmitHandle(MDataRow row);
  15. /// <summary>
  16. /// 构建一个ORM实体转换器
  17. /// </summary>
  18. /// <typeparam name="T">转换的目标类型</typeparam>
  19. /// <param name="schema">表数据架构</param>
  20. public static EmitHandle Create(MDataTable schema)
  21. {
  22. Type tType = typeof(T);
  23. Type rowType = typeof(MDataRow);
  24. DynamicMethod method = new DynamicMethod("RowToT", tType, new Type[] { rowType }, tType);
  25. MethodInfo getValue = rowType.GetMethod("GetItemValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(int) }, null);
  26. ILGenerator gen = method.GetILGenerator();
  27. gen.DeclareLocal(tType);
  28. gen.DeclareLocal(typeof(object));
  29. gen.DeclareLocal(typeof(bool));
  30. gen.Emit(OpCodes.Newobj, tType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null));
  31. gen.Emit(OpCodes.Stloc_0);
  32. int ordinal = -1;
  33. foreach (FieldInfo field in tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
  34. {
  35. string fieldName = field.Name.TrimStart('_');
  36. ordinal = schema.GetOrdinal(fieldName);
  37. if (ordinal > -1)
  38. {
  39. Label retFalse = gen.DefineLabel();
  40. gen.Emit(OpCodes.Ldarg_0);
  41. gen.Emit(OpCodes.Ldc_I4, ordinal);
  42. gen.Emit(OpCodes.Call, getValue);
  43. gen.Emit(OpCodes.Stloc_1);
  44. gen.Emit(OpCodes.Ldloc_1);
  45. gen.Emit(OpCodes.Ldnull);
  46. gen.Emit(OpCodes.Ceq);
  47. gen.Emit(OpCodes.Stloc_2);
  48. gen.Emit(OpCodes.Ldloc_2);
  49. gen.Emit(OpCodes.Brtrue_S, retFalse);//为null值,跳过
  50. gen.Emit(OpCodes.Ldloc_0);
  51. gen.Emit(OpCodes.Ldloc_1);
  52. EmitCastObj(gen, field.FieldType);
  53. gen.Emit(OpCodes.Stfld, field);
  54. gen.MarkLabel(retFalse);//继续下一个循环
  55. }
  56. }
  57. gen.Emit(OpCodes.Ldloc_0);
  58. gen.Emit(OpCodes.Ret);
  59. return method.CreateDelegate(typeof(EmitHandle)) as EmitHandle;
  60. }
  61. private static void EmitCastObj(ILGenerator il, Type targetType)
  62. {
  63. if (targetType.IsValueType)
  64. {
  65. il.Emit(OpCodes.Unbox_Any, targetType);
  66. }
  67. else
  68. {
  69. il.Emit(OpCodes.Castclass, targetType);
  70. }
  71. }
  72. }
  73. }