我有几种方法可以返回不同的通用列表。
.net中是否存在任何类静态方法或将任何列表转换为数据表的方法?我能想象的唯一一件事就是使用反射来做到这一点。
如果我有这个:
List<Whatever> whatever = new List<Whatever>();
(下面的代码当然行不通,但是我希望有以下可能性:
DataTable dt = (DataTable) whatever;
这是使用NuGet的FastMember进行的 2013年不错的更新:
IEnumerable<SomeType> data = ... DataTable table = new DataTable(); using(var reader = ObjectReader.Create(data)) { table.Load(reader); }
这使用FastMember的元编程API以获得最佳性能。如果要将其限制为特定成员(或强制执行命令),则也可以这样做:
IEnumerable<SomeType> data = ... DataTable table = new DataTable(); using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) { table.Load(reader); }
编辑的 Dis /声明者 : FastMember是Marc Gravell的项目。它的黄金和全蝇!
是的,这与这个完全相反。反射就足够了- 或者如果您需要更快,则HyperDescriptor在2.0或Expression3.5中。实际上,HyperDescriptor应该绰绰有余。
HyperDescriptor
Expression
例如:
// remove "this" if not on C# 3.0 / .NET 3.5 public static DataTable ToDataTable<T>(this IList<T> data) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T)); DataTable table = new DataTable(); for(int i = 0 ; i < props.Count ; i++) { PropertyDescriptor prop = props[i]; table.Columns.Add(prop.Name, prop.PropertyType); } object[] values = new object[props.Count]; foreach (T item in data) { for (int i = 0; i < values.Length; i++) { values[i] = props[i].GetValue(item); } table.Rows.Add(values); } return table; }
现在只需一行,您就可以使它比反射快很多倍(通过启用HyperDescriptorobject- type T)。
T
编辑再绩效查询;这是带有结果的测试台:
Vanilla 27179 Hyper 6997
我怀疑瓶颈已经从成员访问转变为DataTable绩效…我怀疑您会在此方面做很多改进…
DataTable
码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; public class MyData { public int A { get; set; } public string B { get; set; } public DateTime C { get; set; } public decimal D { get; set; } public string E { get; set; } public int F { get; set; } } static class Program { static void RunTest(List<MyData> data, string caption) { GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); GC.WaitForFullGCComplete(); Stopwatch watch = Stopwatch.StartNew(); for (int i = 0; i < 500; i++) { data.ToDataTable(); } watch.Stop(); Console.WriteLine(caption + "\t" + watch.ElapsedMilliseconds); } static void Main() { List<MyData> foos = new List<MyData>(); for (int i = 0 ; i < 5000 ; i++ ){ foos.Add(new MyData { // just gibberish... A = i, B = i.ToString(), C = DateTime.Now.AddSeconds(i), D = i, E = "hello", F = i * 2 }); } RunTest(foos, "Vanilla"); Hyper.ComponentModel.HyperTypeDescriptionProvider.Add( typeof(MyData)); RunTest(foos, "Hyper"); Console.ReadLine(); // return to exit } }