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

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

  • 相关阅读:
    LeetCode1049. 最后一块石头的重量 II
    LeetCode416. 分割等和子集
    LeetCode96. 不同的二叉搜索树
    LeetCode343. 整数拆分
    python笔记---内置容器
    Numpy学习笔记(一)
    tensorflow入门代码分析
    神经网络
    回归算法
    机器学习入门笔记
  • 原文地址:https://www.cnblogs.com/jinyu20180311/p/10503796.html
Copyright © 2020-2023  润新知