代码语言:javascript复制
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
代码语言:javascript复制 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 }
代码语言:javascript复制 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 }