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);
}
}
}
}