1 public static class EntityConverter 2 { 3 /// <summary> 4 /// DataTable生成实体 5 /// </summary> 6 /// <typeparam name="T"></typeparam> 7 /// <param name="dataTable"></param> 8 /// <returns></returns> 9 public static IEnumerable<T> ToList<T>(this DataTable dataTable) where T : class, new() 10 { 11 if (dataTable == null) 12 throw new ArgumentNullException(nameof(dataTable)); 13 14 List<T> collection = new List<T>(dataTable.Rows.Count); 15 if (dataTable.Rows.Count == 0) 16 { 17 return collection; 18 } 19 Func<DataRow, T> func = ToExpression<T>(dataTable.Rows[0]); 20 21 foreach (DataRow dr in dataTable.Rows) 22 { 23 collection.Add(func(dr)); 24 } 25 return collection; 26 } 27 28 /// <summary> 29 /// 生成表达式 30 /// </summary> 31 /// <typeparam name="T"></typeparam> 32 /// <param name="dataRow"></param> 33 /// <returns></returns> 34 public static Func<DataRow, T> ToExpression<T>(DataRow dataRow) where T : class, new() 35 { 36 if (dataRow == null) throw new ArgumentNullException("dataRow", "当前对象为null 无法转换成实体"); 37 ParameterExpression paramter = Expression.Parameter(typeof(DataRow), "dr"); 38 List<MemberBinding> binds = new List<MemberBinding>(); 39 for (int i = 0; i < dataRow.ItemArray.Length; i++) 40 { 41 String colName = dataRow.Table.Columns[i].ColumnName; 42 PropertyInfo pInfo = typeof(T).GetProperty(colName); 43 if (pInfo == null) continue; 44 MethodInfo mInfo = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(String) }).MakeGenericMethod(pInfo.PropertyType); 45 MethodCallExpression call = Expression.Call(mInfo, paramter, Expression.Constant(colName, typeof(String))); 46 MemberAssignment bind = Expression.Bind(pInfo, call); 47 binds.Add(bind); 48 } 49 MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(T)), binds.ToArray()); 50 return Expression.Lambda<Func<DataRow, T>>(init, paramter).Compile(); 51 } 52 }
list转datatable
1 public class ObjectShredder<T> 2 { 3 private System.Reflection.FieldInfo[] _fi; 4 private System.Reflection.PropertyInfo[] _pi; 5 private System.Collections.Generic.Dictionary<string, int> _ordinalMap; 6 private System.Type _type; 7 8 // ObjectShredder constructor. 9 public ObjectShredder() 10 { 11 _type = typeof(T); 12 _fi = _type.GetFields(); 13 _pi = _type.GetProperties(); 14 _ordinalMap = new Dictionary<string, int>(); 15 } 16 17 /// <summary> 18 /// Loads a DataTable from a sequence of objects. 19 /// </summary> 20 /// <param name="source">The sequence of objects to load into the DataTable.</param> 21 /// <param name="table">The input table. The schema of the table must match that 22 /// the type T. If the table is null, a new table is created with a schema 23 /// created from the public properties and fields of the type T.</param> 24 /// <param name="options">Specifies how values from the source sequence will be applied to 25 /// existing rows in the table.</param> 26 /// <returns>A DataTable created from the source sequence.</returns> 27 public DataTable Shred(IEnumerable<T> source, DataTable table, LoadOption? options) 28 { 29 // Load the table from the scalar sequence if T is a primitive type. 30 if (typeof(T).IsPrimitive) 31 { 32 return ShredPrimitive(source, table, options); 33 } 34 35 // Create a new table if the input table is null. 36 if (table == null) 37 { 38 table = new DataTable(typeof(T).Name); 39 } 40 41 // Initialize the ordinal map and extend the table schema based on type T. 42 table = ExtendTable(table, typeof(T)); 43 44 // Enumerate the source sequence and load the object values into rows. 45 table.BeginLoadData(); 46 using (IEnumerator<T> e = source.GetEnumerator()) 47 { 48 while (e.MoveNext()) 49 { 50 if (options != null) 51 { 52 table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options); 53 } 54 else 55 { 56 table.LoadDataRow(ShredObject(table, e.Current), true); 57 } 58 } 59 } 60 table.EndLoadData(); 61 62 // Return the table. 63 return table; 64 } 65 66 public DataTable ShredPrimitive(IEnumerable<T> source, DataTable table, LoadOption? options) 67 { 68 // Create a new table if the input table is null. 69 if (table == null) 70 { 71 table = new DataTable(typeof(T).Name); 72 } 73 74 if (!table.Columns.Contains("Value")) 75 { 76 table.Columns.Add("Value", typeof(T)); 77 } 78 79 // Enumerate the source sequence and load the scalar values into rows. 80 table.BeginLoadData(); 81 using (IEnumerator<T> e = source.GetEnumerator()) 82 { 83 Object[] values = new object[table.Columns.Count]; 84 while (e.MoveNext()) 85 { 86 values[table.Columns["Value"].Ordinal] = e.Current; 87 88 if (options != null) 89 { 90 table.LoadDataRow(values, (LoadOption)options); 91 } 92 else 93 { 94 table.LoadDataRow(values, true); 95 } 96 } 97 } 98 table.EndLoadData(); 99 100 // Return the table. 101 return table; 102 } 103 104 public object[] ShredObject(DataTable table, T instance) 105 { 106 107 FieldInfo[] fi = _fi; 108 PropertyInfo[] pi = _pi; 109 110 if (instance.GetType() != typeof(T)) 111 { 112 // If the instance is derived from T, extend the table schema 113 // and get the properties and fields. 114 ExtendTable(table, instance.GetType()); 115 fi = instance.GetType().GetFields(); 116 pi = instance.GetType().GetProperties(); 117 } 118 119 // Add the property and field values of the instance to an array. 120 Object[] values = new object[table.Columns.Count]; 121 foreach (FieldInfo f in fi) 122 { 123 values[_ordinalMap[f.Name]] = f.GetValue(instance); 124 } 125 126 foreach (PropertyInfo p in pi) 127 { 128 values[_ordinalMap[p.Name]] = p.GetValue(instance, null); 129 } 130 131 // Return the property and field values of the instance. 132 return values; 133 } 134 135 public DataTable ExtendTable(DataTable table, Type type) 136 { 137 // Extend the table schema if the input table was null or if the value 138 // in the sequence is derived from type T. 139 foreach (FieldInfo f in type.GetFields()) 140 { 141 if (!_ordinalMap.ContainsKey(f.Name)) 142 { 143 // Add the field as a column in the table if it doesn't exist 144 // already. 145 DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name] 146 : table.Columns.Add(f.Name, f.FieldType); 147 148 // Add the field to the ordinal map. 149 _ordinalMap.Add(f.Name, dc.Ordinal); 150 } 151 } 152 foreach (PropertyInfo p in type.GetProperties()) 153 { 154 if (!_ordinalMap.ContainsKey(p.Name)) 155 { 156 // Add the property as a column in the table if it doesn't exist 157 // already. 158 DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name] 159 : table.Columns.Add(p.Name, p.PropertyType); 160 161 // Add the property to the ordinal map. 162 _ordinalMap.Add(p.Name, dc.Ordinal); 163 } 164 } 165 166 // Return the table. 167 return table; 168 } 169 }
1 public static DataTable CopyToDataTable<T>(this IEnumerable<T> source) 2 { 3 return new ObjectShredder<T>().Shred(source, null, null); 4 } 5 6 public static DataTable CopyToDataTable<T>(this IEnumerable<T> source, 7 DataTable table, LoadOption? options) 8 { 9 return new ObjectShredder<T>().Shred(source, table, options); 10 }