120 lines
4.4 KiB
C#
120 lines
4.4 KiB
C#
|
|
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>
|
|||
|
|
/// <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>[500<30><30><EFBFBD><EFBFBD>],<2C><><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>]
|
|||
|
|
/// </summary>
|
|||
|
|
internal class FastToT<T>
|
|||
|
|
{
|
|||
|
|
public delegate T EmitHandle(MDataRow row);
|
|||
|
|
/// <summary>
|
|||
|
|
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ORMʵ<4D><CAB5>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
|
|||
|
|
/// </summary>
|
|||
|
|
/// <typeparam name="T">ת<><D7AA><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD></typeparam>
|
|||
|
|
/// <param name="schema"><3E><><EFBFBD><EFBFBD><EFBFBD>ݼܹ<DDBC></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();//<2F><>ʼ<EFBFBD><CABC>дIL<49><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|
|||
|
|
gen.DeclareLocal(tType);
|
|||
|
|
gen.DeclareLocal(typeof(object));
|
|||
|
|
gen.DeclareLocal(typeof(bool)); //<2F>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>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)//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>
|
|||
|
|
{
|
|||
|
|
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();//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9>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ֵ<6C><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|
|||
|
|
gen.Emit(OpCodes.Ldloc_0);//ʵ<><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
gen.Emit(OpCodes.Ldloc_1);//<2F><><EFBFBD>Ե<EFBFBD>ֵ
|
|||
|
|
EmitCastObj(gen, field.FieldType);//<2F><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
|
|||
|
|
gen.Emit(OpCodes.Stfld, field);//<2F><>ʵ<EFBFBD>帳ֵ System.Object.FieldSetter(String typeName, String fieldName, Object val)
|
|||
|
|
|
|||
|
|
gen.MarkLabel(retFalse);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ѭ<EFBFBD><D1AD>
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|