忘了为什么要把IEnumerable
IEnumerable
1 public static DataTable ToDataTable(IEnumerable collection)
2 {
3 var props = typeof(T).GetProperties();
4 var dt = new DataTable();
5 dt.Columns.AddRange(props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray());
6 if (collection.Count() > 0)
7 {
8 for (int i = 0; i < collection.Count(); i++)
9 {
10 ArrayList tempList = new ArrayList();
11 foreach (PropertyInfo pi in props)
12 {
13 object obj = pi.GetValue(collection.ElementAt(i), null);
14 tempList.Add(obj);
15 }
16 object[] array = tempList.ToArray();
17 dt.LoadDataRow(array, true);
18 }
19 }
20 return dt;
21 }
反射效率低,自然而然我们又想到了表达式树这个东西,表达式树的其中一个作用就是实现了反射的功能同时避免了反射带来的效率问题。
首先咱打算构造一个形如obj=>obj.Property的表达式树。
1 //构造委托类似FuncgetAge = u => u.Age; 2 static Funcobject > GetGetDelegate(PropertyInfo p) 3 { 4 var param_obj = Expression.Parameter(typeof(T), "obj"); 5 //lambda的方法体 u.Age 6 var pGetter = Expression.Property(param_obj, p); 7 //编译lambda 8 return Expression.Lambda object>>(pGetter, param_obj).Compile(); 9 } 10 11 static object FastGetValue (this PropertyInfo property, T t) 12 { 13 return GetGetDelegate (property)(t); 14 }
然后我们就可以将上述反射代码改成如下:
1 public static DataTable ToTable(this IEnumerable collection)
2 {
3 var props = typeof(T).GetProperties();
4
5 var dt = new DataTable();
6 dt.Columns.AddRange(
7 props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray()
8 );
9
10 collection.ToList().ForEach(
11 i => dt.Rows.Add(props.Select(p => p.FastGetValue(i)).ToArray())
12 );
13
14 return dt;
15 }
很好,咱们没用到反射就把工作完成了。但是效率真的有提升吗?我看未必。后者只是将前者的pi.GetValue(collection.ElementAt(i), null)改成p => p.FastGetValue(i),而FastGetValue会每次都去构造表达式树然后编译Lambda,针对IEnumerable
1 static Funcobject []> GetGetDelegate(PropertyInfo[] ps) 2 { 3 var param_obj = Expression.Parameter(typeof(T), "obj"); 4 Expression newArrayExpression = Expression.NewArrayInit(typeof(object), ps.Select(p => Expression.Property(param_obj, p))); 5 return Expression.Lambda object[]>>(newArrayExpression, param_obj).Compile(); 6 }
这里我将属性委托从返回单个属性值变为返回所有属性值数组,我们就可以这么使用。
1 public static DataTable ToTable(this IEnumerable collection)
2 {
3 var props = typeof(T).GetProperties();
4 var func = GetGetDelegate(props);
5 var dt = new DataTable();
6 dt.Columns.AddRange(
7 props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray()
8 );
9 collection.ToList().ForEach(i => dt.Rows.Add(func(i)));
10
11 return dt;
12 }
上述代码可知,使用时只需要构造一次委托即可。另外,这个方法我没使用过,大家可以试试看,哇哈哈哈哈。
转载请注明本文出处:http://www.cnblogs.com/newton/archive/2013/01/09/2853083.html