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

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

原文地址:https://www.cnblogs.com/jinyu20180311/p/10503796.html