使用Emit把Datatable转换为对象集合(List<T>)
2013-09-29 17:11
453 查看
Emit生成动态方法部分摘自网上,但是经过修改,加入了对委托的缓存以及类结构的调整,使之调用更简洁方便。大致的思路是:要实现转换datatable到某个指定对象的集合,本质是实现转换一个datarow到一个指定的对象。利用Emit动态构造该方法并缓存起来,调用时从缓存查找出来并调用,就这么简单。上代码:
/// <summary> /// 把datatable转换为对象集合列表List<T> /// </summary> public class DataTableConvert { //把DataRow转换为对象的委托声明 private delegate T Load<T>(DataRow dataRecord); //用于构造Emit的DataRow中获取字段的方法信息 private static readonly MethodInfo getValueMethod = typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) }); //用于构造Emit的DataRow中判断是否为空行的方法信息 private static readonly MethodInfo isDBNullMethod = typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) }); //使用字典存储实体的类型以及与之对应的Emit生成的转换方法 private static Dictionary<Type, Delegate> rowMapMethods = new Dictionary<Type, Delegate>(); public static List<T> ToList<T>(DataTable dt) { List<T> list = new List<T>(); if (dt == null) return list; //声明 委托Load<T>的一个实例rowMap Load<T> rowMap = null; //从rowMapMethods查找当前T类对应的转换方法,没有则使用Emit构造一个。 if (!rowMapMethods.ContainsKey(typeof(T))) { DynamicMethod method = new DynamicMethod("DynamicCreateEntity_" + typeof(T).Name, typeof(T), new Type[] { typeof(DataRow) }, typeof(T), true); ILGenerator generator = method.GetILGenerator(); LocalBuilder result = generator.DeclareLocal(typeof(T)); generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); generator.Emit(OpCodes.Stloc, result); for (int index = 0; index < dt.Columns.Count; index++) { PropertyInfo propertyInfo = typeof(T).GetProperty(dt.Columns[index].ColumnName,StringComparison.CurrentCultureIgnoreCase); Label endIfLabel = generator.DefineLabel(); if (propertyInfo != null && propertyInfo.GetSetMethod() != null) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, index); generator.Emit(OpCodes.Callvirt, isDBNullMethod); generator.Emit(OpCodes.Brtrue, endIfLabel); generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4, index); generator.Emit(OpCodes.Callvirt, getValueMethod); generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); generator.MarkLabel(endIfLabel); } } generator.Emit(OpCodes.Ldloc, result); generator.Emit(OpCodes.Ret); //构造完成以后传给rowMap rowMap = (Load<T>)method.CreateDelegate(typeof(Load<T>)); } else { rowMap = (Load<T>)rowMapMethods[typeof(T)]; } //遍历Datatable的rows集合,调用rowMap把DataRow转换为对象(T) foreach (DataRow info in dt.Rows) list.Add(rowMap(info)); return list; } }
相关文章推荐
- 再谈使用Emit把Datatable转换为对象集合(List<T>)
- 再谈使用Emit把Datatable转换为对象集合(List<T>)
- 再谈使用Emit把Datatable转换为对象集合(List<T>)
- 使用扩展方法将DataTable转换为List<T>
- 将DataTable转换为List<T>对象遇到问题:类型“System.Int64”的对象无法转换为类型“System.Int32”
- 将list<对象>转换成DataTable,把DataTable转换成参数传入存储过程实现批量插入数据
- DataTable转换List<T>集合的方法
- 将DataTable转换成泛型集合IList<>
- 将DataTable转换成List<T>泛型集合助手类
- 将一个DataTable转换成一个List<T>的泛型集合
- 【代码】DataTable转换成List<T>集合
- 将一个DataTable转换成一个List<T>的泛型集合
- C#使用反射将DataTable转换List<T>
- 将List<Object[]>数组对象转换成List<HashMap<String, Object>>集合对象
- 将DataTable转换为List<T>对象遇到问题:类型“System.Int64”的对象无法转换为类型“System.Int32”。
- C#将DataTable转换成单个T实体和List<T>集合
- 将泛型集合类(List<T>)转换成DataTable,返回的DataTable所有列的数据类型为string型,且列顺序与字符串提供的字段顺序一致
- linq之将IEnumerable<T>类型的集合转换为DataTable类型 (转载)
- List<T>转换为DataTable
- 把List<T>转换为DataTable