Emit实现DataRow转化成强类型的T
来博客园已经很多年了,一直很懒,没写过博客,都是偷偷的关注园子里大牛门
看他们的动向,跟着他们的脚步学习知识。
这次也算是一点反馈吧,记得前一段时间看过一个园友写过一个DataTable转换成List<T>的文章
受到了不少启发,于是有了下面的一小段代码,写他的目的也不算是重复的造轮子,只是为了温习一下Emit
不然久了真的忘记了。
废话少说了,直接上代码,有注释的哦,我就不解释了
想学习Emit的同学可以对照OpCodes的指令来看,肯定会有收获的
static Func<DataRow, T> CreateFunc<T>() where T : new()
{
Type classType = typeof(T);
DynamicMethod method = new DynamicMethod("", typeof(T), new Type[] { typeof(DataRow) }, true);
ILGenerator il = method.GetILGenerator();
//new一个需要返回的对象
il.DeclareLocal(classType);
il.Emit(OpCodes.Newobj, classType.GetConstructor(Type.EmptyTypes));
il.Emit(OpCodes.Stloc_0); //var t = new T()
//取出dr中所有的列名集合
il.DeclareLocal(typeof(DataColumnCollection));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Callvirt, typeof(DataRow).GetMethod("get_Table"));
il.Emit(OpCodes.Callvirt, typeof(DataTable).GetMethod("get_Columns"));
il.Emit(OpCodes.Stloc_1); //var columns = dr.Table.Columns
var props = classType.GetProperties(BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Public);
foreach (var property in props)
{
var label = il.DefineLabel();
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldstr, property.Name);
il.Emit(OpCodes.Callvirt, typeof(DataColumnCollection).GetMethod("Contains"));
//判断dr中是否有此列名
il.Emit(OpCodes.Brfalse, label); // if (!columns.Contains("xx"))
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldstr, property.Name);
//取出dr中对应的列的值
il.Emit(OpCodes.Callvirt, typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(string) })); //var temp = dr["xx"]
//对取出的值拆箱
il.Emit(OpCodes.Unbox_Any, property.PropertyType);
var temp = il.DeclareLocal(property.PropertyType);
il.Emit(OpCodes.Stloc, temp);
//t.xx = temp
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldloc, temp);
il.Emit(OpCodes.Callvirt, property.GetSetMethod());
il.MarkLabel(label);
}
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
return method.CreateDelegate(typeof(Func<DataRow, T>)) as Func<DataRow, T>;
}
下面给出一个测试的代码片段
public class User
{
public int ID { get; set; }
public string Name { get; set; }
}
var func = CreateFunc<User>();
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
//dt.Columns.Add("name", typeof(string));
var dr = dt.NewRow();
dr[0] = 13;
//dr[1] = "coffee";
dt.Rows.Add(dr);
var user = func(dr);
第一次发文,斗胆放上首页,请各位大牛不吝赐教~~~
浙公网安备 33010602011771号