tijian_tieying/web/cyqdata-master/Table/FastToT.cs
2025-02-20 12:14:39 +08:00

120 lines
4.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using CYQ.Data.Table;
namespace CYQ.Data.Tool
{
/// <summary>
/// 快速转换类[数据量越大[500条起],性能越高]
/// </summary>
internal class FastToT<T>
{
public delegate T EmitHandle(MDataRow row);
/// <summary>
/// 构建一个ORM实体转换器
/// </summary>
/// <typeparam name="T">转换的目标类型</typeparam>
/// <param name="schema">表数据架构</param>
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();//开始编写IL方法。
gen.DeclareLocal(tType);
gen.DeclareLocal(typeof(object));
gen.DeclareLocal(typeof(bool)); //分别定义了一个Type t,object o,bool b;
gen.Emit(OpCodes.Newobj, tType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null));
gen.Emit(OpCodes.Stloc_0);//t= new T();
int ordinal = -1;
List<FieldInfo> fileds = new List<FieldInfo>();
fileds.AddRange(tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));
if (tType.BaseType.Name != "Object" && tType.BaseType.Name != "OrmBase")
{
FieldInfo[] items = tType.BaseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (FieldInfo item in items)
{
bool isAdd = true;
foreach (FieldInfo f in fileds)//这里检测去重复。
{
if (item.Name == f.Name)
{
isAdd = false;
break;
}
}
if (isAdd)
{
fileds.Add(item);
}
}
}
foreach (FieldInfo field in fileds)
{
string fieldName = field.Name;
if(fieldName[0]=='<')
{
fieldName=fieldName.Substring(1,fieldName.IndexOf('>')-1);
}
ordinal = schema.Columns.GetIndex(fieldName.TrimStart('_'));
if (ordinal == -1)
{
ordinal = schema.Columns.GetIndex(fieldName);
}
if (ordinal > -1)
{
Label retFalse = gen.DefineLabel();//定义标签goto;
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldc_I4, ordinal);
gen.Emit(OpCodes.Call, getValue);//Call GetItemValue(ordinal);
gen.Emit(OpCodes.Stloc_1); // o=GetItemValue(ordinal);
gen.Emit(OpCodes.Ldloc_1);
gen.Emit(OpCodes.Ldnull);
gen.Emit(OpCodes.Ceq);// if (o==null)
gen.Emit(OpCodes.Stloc_2); //b=o==null;
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);//对实体赋值 System.Object.FieldSetter(String typeName, String fieldName, Object val)
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);
}
}
}
}