using System; using System.Collections.Generic; using System.Text; using System.Reflection.Emit; using System.Reflection; using Ant.ORM.Table; namespace Ant.ORM.Tool { /// /// 快速转换类[数据量越大[500条起],性能越高] /// internal class FastToT { public delegate T EmitHandle(MDataRow row); /// /// 构建一个ORM实体转换器 /// /// 转换的目标类型 /// 表数据架构 public static EmitHandle Create(MDataTable schema) { Type tType = typeof(T); Type rowType = typeof(MDataRow); DynamicMethod method = new DynamicMethod("RowToT", tType, new Type[] { rowType }, tType); MethodInfo getValue = rowType.GetMethod("GetItemValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(int) }, null); ILGenerator gen = method.GetILGenerator(); gen.DeclareLocal(tType); gen.DeclareLocal(typeof(object)); gen.DeclareLocal(typeof(bool)); gen.Emit(OpCodes.Newobj, tType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null)); gen.Emit(OpCodes.Stloc_0); int ordinal = -1; foreach (FieldInfo field in tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) { string fieldName = field.Name.TrimStart('_'); ordinal = schema.GetOrdinal(fieldName); if (ordinal > -1) { Label retFalse = gen.DefineLabel(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldc_I4, ordinal); gen.Emit(OpCodes.Call, getValue); gen.Emit(OpCodes.Stloc_1); gen.Emit(OpCodes.Ldloc_1); gen.Emit(OpCodes.Ldnull); gen.Emit(OpCodes.Ceq); gen.Emit(OpCodes.Stloc_2); gen.Emit(OpCodes.Ldloc_2); gen.Emit(OpCodes.Brtrue_S, retFalse);//为null值,跳过 gen.Emit(OpCodes.Ldloc_0); gen.Emit(OpCodes.Ldloc_1); EmitCastObj(gen, field.FieldType); gen.Emit(OpCodes.Stfld, field); gen.MarkLabel(retFalse);//继续下一个循环 } } gen.Emit(OpCodes.Ldloc_0); gen.Emit(OpCodes.Ret); return method.CreateDelegate(typeof(EmitHandle)) as EmitHandle; } private static void EmitCastObj(ILGenerator il, Type targetType) { if (targetType.IsValueType) { il.Emit(OpCodes.Unbox_Any, targetType); } else { il.Emit(OpCodes.Castclass, targetType); } } } }