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

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

  • 相关阅读:
    Jquery 添加插件
    后台添加前台标签
    jQuery.validate 中文API
    jquery validate 详解二
    jquery validate 详解一
    System.Collections里的一些接口
    C#中 Reference Equals, == , Equals的区别
    关于iOS原生条形码扫描,你需要注意的两三事
    layoutSubviews何时调用的问题(转)
    layoutSubviews总结
  • 原文地址:https://www.cnblogs.com/nqicecoffee/p/3387539.html
Copyright © 2020-2023  润新知