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

  第一次发文,斗胆放上首页,请各位大牛不吝赐教~~~

posted @ 2013-10-25 11:17  NqIceCoffee  阅读(1632)  评论(3编辑  收藏  举报