Hier ist ein schönes 2013-Update mit FastMember von NuGet:
IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data)) {
table.Load(reader);
}
Dies verwendet die Meta-Programmier-API von FastMember für maximale Leistung. Wenn Sie es auf bestimmte Mitglieder beschränken möchten (oder die Anordnung durchsetzen möchten), können Sie dies auch tun:
IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) {
table.Load(reader);
}
Dis / Claimer des Herausgebers : FastMember ist ein Marc Gravell-Projekt. Sein Gold und seine Fliegen!
Ja, das ist so ziemlich das genaue Gegenteil von diesem ; Reflexion würde ausreichen - oder wenn Sie schneller brauchen, HyperDescriptorin 2.0 oder vielleicht Expressionin 3.5. Eigentlich HyperDescriptorsollte mehr als ausreichend sein.
Beispielsweise:
// 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;
}
Mit einer Zeile können Sie dies jetzt um ein Vielfaches schneller als die Reflexion machen (indem Sie HyperDescriptorden Objekttyp aktivieren T).
Bearbeiten Sie die Leistungsabfrage. Hier ist ein Prüfstand mit Ergebnissen:
Vanilla 27179
Hyper 6997
Ich vermute, dass sich der Engpass vom Mitgliederzugriff auf die DataTableLeistung verlagert hat ... Ich bezweifle, dass Sie dies erheblich verbessern werden ...
Code:
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
}
}