• c#将List转换成DataTable(采用Emit)


    前段时间通过网上查找,使用emit将Datatable,DataReader转换成List<T>了。这是从数据库到展示。

    但是最近整理Hikari(我写的数据库连接池),发现c#里面数据库客户端驱动一般会提供一个BulkCopy的类,一般接口是DataTable,可以批量插入。所以又研究了如何把List<T>转DataTable.

    一般方法是全部反射,我就不说了。这里只说emit,记录下下次用。

    这里创建动态方法(委托)有个范围问题。我举个例子

    假如有Pseron类。

    public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public int Score { get; set; }
        }

    1.方法是这样的

     public static void PersonToDataRow(Person person, DataTable dt)
            {
                DataRow row=  dt.NewRow();
                row["Name"] = person.Name;
                row["Age"] = person.Age;
                row["Score"] = person.Score;
                dt.Rows.Add(row);
            }

    2.方法是这样的

     public static void PersonToDataRow(Person person, DataRow row)
            {
              
                row["Name"] = person.Name;
                row["Age"] = person.Age;
                row["Score"] = person.Score;
            }

    这两种就有范围问题。

    第一类创建动态方法代码如下:

    需要有一个委托定义: public delegate void LoadDataRow<T>(T obj,DataTable dr);

    创建代码

     public static DynamicMethod ConvertDataRow<T>()
            {
                DynamicMethod method = new DynamicMethod(typeof(T).Name+"ToDataRow", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null,
                    new Type[] { typeof(T), typeof(DataRow) }, typeof(EntityContext).Module, true);
                ILGenerator generator = method.GetILGenerator();
                LocalBuilder reslut = generator.DeclareLocal(typeof(DataRow));
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Call, typeof(DataTable).GetMethod("NewRow"));
                generator.Emit(OpCodes.Stloc, reslut);
                foreach (var p in typeof(T).GetProperties())
                {
                    generator.Emit(OpCodes.Ldloc, reslut);
                  
                    generator.Emit(OpCodes.Ldstr, p.Name);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Call, p.GetGetMethod());//
                    if (p.PropertyType.IsValueType)
                         generator.Emit(OpCodes.Box, p.PropertyType);//一直在折腾这个地方,哎
                    else
                        generator.Emit(OpCodes.Castclass, p.PropertyType);
    
                    generator.Emit(OpCodes.Call, typeof(DataRow).GetMethod("set_Item", new Type[] { typeof(string), typeof(object) }));
                }
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Call, typeof(DataTable).GetMethod("get_Rows"));
                generator.Emit(OpCodes.Ldloc, reslut);
                generator.Emit(OpCodes.Call, typeof(DataRowCollection).GetMethod("Add", new Type[] { typeof(DataRow) }));
                generator.Emit(OpCodes.Ret);
    
                return method;
               
            }
    

    调用上面代码创建委托即可。

    第二类创建代码:

    需要定义一个委托:public delegate void EntityToRow<T>(T obj, DataRow row);

    创建代码:

      private static DynamicMethod BuildMethodToRow<T>()
            {
                DynamicMethod method = new DynamicMethod(typeof(T).Name+ "ConvertToDataRow", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,null,
                        new Type[] { typeof(T),typeof(DataRow) }, typeof(EntityContext).Module, true);
                ILGenerator generator = method.GetILGenerator();
                foreach (var p in typeof(T).GetProperties())
                {
                    var endIfLabel = generator.DefineLabel();
                    generator.Emit(OpCodes.Ldarg_1);
                    generator.Emit(OpCodes.Ldstr, p.Name);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Call, p.GetGetMethod());//获取
                    if (p.PropertyType.IsValueType || p.PropertyType == typeof(string))
                        generator.Emit(OpCodes.Box,p.PropertyType);//装箱                                                        
                    else
                        generator.Emit(OpCodes.Castclass, p.PropertyType);
                    generator.Emit(OpCodes.Call, dataRowAssembly.SetValueMethod);
                }
                generator.Emit(OpCodes.Ret);
                return method;
            }
    

    调用上面代码创建委托即可。

  • 相关阅读:
    2016北京集训测试赛(十四)Problem A: 股神小L
    2016北京集训测试赛(十三) Problem B: 网络战争
    BZOJ 3473 字符串
    2016北京集训测试赛(十一)Problem C: 树链问题
    微信服务号登陆优化
    重新认识下数组的concat方法
    微信服务号开发碰到的缓存问题!
    关于微信服务号开发的一些总结!
    JQ-weui中的日期选择控件关于时间段的设置!
    用json方法来作深拷贝应该知道的一点东西!
  • 原文地址:https://www.cnblogs.com/jinyu20180311/p/10503796.html
Copyright © 2020-2023  润新知