我有几种方法可以返回不同的通用列表。
.net中是否存在任何类静态方法或将任何列表转换为数据表的方法?我能想象的唯一一件事就是使用反射来做到这一点。
如果我有这个:
List<Whatever> whatever = new List<Whatever>();
(下一个代码当然不起作用,但是我希望有以下可能性:
DataTable dt = (DataTable) whatever;
我有几种方法可以返回不同的通用列表。
.net中是否存在任何类静态方法或将任何列表转换为数据表的方法?我能想象的唯一一件事就是使用反射来做到这一点。
如果我有这个:
List<Whatever> whatever = new List<Whatever>();
(下一个代码当然不起作用,但是我希望有以下可能性:
DataTable dt = (DataTable) whatever;
Answers:
这是使用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或Expression
3.5。实际上,HyperDescriptor
应该绰绰有余。
例如:
// 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;
}
现在只需一行,您就可以使它比反射快很多倍(通过启用HyperDescriptor
object-type T
)。
编辑再绩效查询;这是带有结果的测试台:
Vanilla 27179
Hyper 6997
我怀疑瓶颈已经从成员访问转变为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
}
}
我不得不修改Marc Gravell的示例代码以处理可为空的类型和空值。我在下面包括了一个工作版本。谢谢马克。
public static DataTable ToDataTable<T>(this IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
public static DataTable ToDataTable<TKey, T>(this IEnumerable<IGrouping<TKey, T>> data)
然后,在foreach循环之前添加一个额外的列: table.Columns.Add("Key", Nullable.GetUnderlyingType(typeof(TKey)) ?? typeof(TKey));
然后在数据循环周围添加一个循环,在其中循环访问组:foreach(IGrouping <TKey, T>在数据中分组){foreach(在group.Items中的
ToDataTable
方法中存在一个偷偷摸摸的错误。如果T
实现,则接口typeof(T)
可能返回接口类型,而不是对象的实际类,从而导致为空DataTable
。替换为data.First().GetType()
应该可以修复它。
对Marc的答案进行很小的更改,使其可以处理类似于List<string>
数据表的值类型:
public static DataTable ListToDataTable<T>(IList<T> data)
{
DataTable table = new DataTable();
//special handling for value types and string
if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
{
DataColumn dc = new DataColumn("Value");
table.Columns.Add(dc);
foreach (T item in data)
{
DataRow dr = table.NewRow();
dr[0] = item;
table.Rows.Add(dr);
}
}
else
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
foreach (PropertyDescriptor prop in properties)
{
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
try
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
catch (Exception ex)
{
row[prop.Name] = DBNull.Value;
}
}
table.Rows.Add(row);
}
}
return table;
}
这是解决方案的简单组合。它适用于Nullable类型。
public static DataTable ToDataTable<T>(this IList<T> list)
{
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, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in list)
{
for (int i = 0; i < values.Length; i++)
values[i] = props[i].GetValue(item) ?? DBNull.Value;
table.Rows.Add(values);
}
return table;
}
MSDN上的此链接值得一游:如何:在通用类型T不是DataRow的情况下实现CopyToDataTable <T>
这将添加一个扩展方法,使您可以执行此操作:
// Create a sequence.
Item[] items = new Item[]
{ new Book{Id = 1, Price = 13.50, Genre = "Comedy", Author = "Gustavo Achong"},
new Book{Id = 2, Price = 8.50, Genre = "Drama", Author = "Jessie Zeng"},
new Movie{Id = 1, Price = 22.99, Genre = "Comedy", Director = "Marissa Barnes"},
new Movie{Id = 1, Price = 13.40, Genre = "Action", Director = "Emmanuel Fernandez"}};
// Query for items with price greater than 9.99.
var query = from i in items
where i.Price > 9.99
orderby i.Price
select i;
// Load the query results into new DataTable.
DataTable table = query.CopyToDataTable();
上面是另一种方法:
List<WhateEver> lst = getdata();
string json = Newtonsoft.Json.JsonConvert.SerializeObject(lst);
DataTable pDt = JsonConvert.DeserializeObject<DataTable>(json);
public DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
table.Rows.Add(row);
}
return table;
}
马克·格雷夫(Marc Gravell)的答案,但在VB.NET中
Public Shared Function ToDataTable(Of T)(data As IList(Of T)) As DataTable
Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
Dim table As New DataTable()
For i As Integer = 0 To props.Count - 1
Dim prop As PropertyDescriptor = props(i)
table.Columns.Add(prop.Name, prop.PropertyType)
Next
Dim values As Object() = New Object(props.Count - 1) {}
For Each item As T In data
For i As Integer = 0 To values.Length - 1
values(i) = props(i).GetValue(item)
Next
table.Rows.Add(values)
Next
Return table
End Function
试试这个
public static DataTable ListToDataTable<T>(IList<T> lst)
{
currentDT = CreateTable<T>();
Type entType = typeof(T);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entType);
foreach (T item in lst)
{
DataRow row = currentDT.NewRow();
foreach (PropertyDescriptor prop in properties)
{
if (prop.PropertyType == typeof(Nullable<decimal>) || prop.PropertyType == typeof(Nullable<int>) || prop.PropertyType == typeof(Nullable<Int64>))
{
if (prop.GetValue(item) == null)
row[prop.Name] = 0;
else
row[prop.Name] = prop.GetValue(item);
}
else
row[prop.Name] = prop.GetValue(item);
}
currentDT.Rows.Add(row);
}
return currentDT;
}
public static DataTable CreateTable<T>()
{
Type entType = typeof(T);
DataTable tbl = new DataTable(DTName);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entType);
foreach (PropertyDescriptor prop in properties)
{
if (prop.PropertyType == typeof(Nullable<decimal>))
tbl.Columns.Add(prop.Name, typeof(decimal));
else if (prop.PropertyType == typeof(Nullable<int>))
tbl.Columns.Add(prop.Name, typeof(int));
else if (prop.PropertyType == typeof(Nullable<Int64>))
tbl.Columns.Add(prop.Name, typeof(Int64));
else
tbl.Columns.Add(prop.Name, prop.PropertyType);
}
return tbl;
}
It's also possible through XmlSerialization.
The idea is - serialize to `XML` and then `readXml` method of `DataSet`.
I use this code (from an answer in SO, forgot where)
public static string SerializeXml<T>(T value) where T : class
{
if (value == null)
{
return null;
}
XmlSerializer serializer = new XmlSerializer(typeof(T));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = new UnicodeEncoding(false, false);
settings.Indent = false;
settings.OmitXmlDeclaration = false;
// no BOM in a .NET string
using (StringWriter textWriter = new StringWriter())
{
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
{
serializer.Serialize(xmlWriter, value);
}
return textWriter.ToString();
}
}
so then it's as simple as:
string xmlString = Utility.SerializeXml(trans.InnerList);
DataSet ds = new DataSet("New_DataSet");
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
ds.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
ds.ReadXml(reader);
}
Not sure how it stands against all the other answers to this post, but it's also a possibility.
我自己编写了一个小型图书馆来完成此任务。它仅在第一次将对象类型转换为数据表时才使用反射。它发出一个方法,将完成翻译对象类型的所有工作。
它的速度很快。您可以在这里找到它: GoogleCode上的ModelShredder
我还必须提出一个替代解决方案,因为这里列出的所有选项均不适用于我的情况。我使用的是IEnumerable,它返回了IEnumerable,并且无法枚举属性。这达到了目的:
// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ConvertToDataTable<T>(this IEnumerable<T> data)
{
List<IDataRecord> list = data.Cast<IDataRecord>().ToList();
PropertyDescriptorCollection props = null;
DataTable table = new DataTable();
if (list != null && list.Count > 0)
{
props = TypeDescriptor.GetProperties(list[0]);
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
}
if (props != null)
{
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) ?? DBNull.Value;
}
table.Rows.Add(values);
}
}
return table;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.ComponentModel;
public partial class Default3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt = lstEmployee.ConvertToDataTable();
}
public static DataTable ConvertToDataTable<T>(IList<T> list) where T : class
{
try
{
DataTable table = CreateDataTable<T>();
Type objType = typeof(T);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(objType);
foreach (T item in list)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor property in properties)
{
if (!CanUseType(property.PropertyType)) continue;
row[property.Name] = property.GetValue(item) ?? DBNull.Value;
}
table.Rows.Add(row);
}
return table;
}
catch (DataException ex)
{
return null;
}
catch (Exception ex)
{
return null;
}
}
private static DataTable CreateDataTable<T>() where T : class
{
Type objType = typeof(T);
DataTable table = new DataTable(objType.Name);
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(objType);
foreach (PropertyDescriptor property in properties)
{
Type propertyType = property.PropertyType;
if (!CanUseType(propertyType)) continue;
//nullables must use underlying types
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
propertyType = Nullable.GetUnderlyingType(propertyType);
//enums also need special treatment
if (propertyType.IsEnum)
propertyType = Enum.GetUnderlyingType(propertyType);
table.Columns.Add(property.Name, propertyType);
}
return table;
}
private static bool CanUseType(Type propertyType)
{
//only strings and value types
if (propertyType.IsArray) return false;
if (!propertyType.IsValueType && propertyType != typeof(string)) return false;
return true;
}
}
我意识到这已经关闭了一段时间;但是,我有一个解决此特定问题的方法,但需要稍作改动:列和数据表需要预定义/已实例化。然后,我需要简单地将类型插入数据表中。
所以这是我所做的一个例子:
public static class Test
{
public static void Main()
{
var dataTable = new System.Data.DataTable(Guid.NewGuid().ToString());
var columnCode = new DataColumn("Code");
var columnLength = new DataColumn("Length");
var columnProduct = new DataColumn("Product");
dataTable.Columns.AddRange(new DataColumn[]
{
columnCode,
columnLength,
columnProduct
});
var item = new List<SomeClass>();
item.Select(data => new
{
data.Id,
data.Name,
data.SomeValue
}).AddToDataTable(dataTable);
}
}
static class Extensions
{
public static void AddToDataTable<T>(this IEnumerable<T> enumerable, System.Data.DataTable table)
{
if (enumerable.FirstOrDefault() == null)
{
table.Rows.Add(new[] {string.Empty});
return;
}
var properties = enumerable.FirstOrDefault().GetType().GetProperties();
foreach (var item in enumerable)
{
var row = table.NewRow();
foreach (var property in properties)
{
row[property.Name] = item.GetType().InvokeMember(property.Name, BindingFlags.GetProperty, null, item, null);
}
table.Rows.Add(row);
}
}
}
如果您使用的是.NET Core,那么这是2019年的答案-使用Nuget ToDataTable库。优点:
免责声明 -我是ToDataTable的作者
性能 -我涵盖了一些Benchmark .Net测试,并将它们包含在ToDataTable存储库中。结果如下:
创建一个100,000行数据表:
MacOS Windows
Reflection 818.5 ms 818.3 ms
FastMember from 1105.5 ms 976.4 ms
Mark's answer
Improved FastMember 524.6 ms 456.4 ms
ToDataTable 449.0 ms 376.5 ms
Marc的答案中建议的FastMember方法似乎比使用反射的Mary的答案更差,但是我使用FastMember 推出了另一种方法TypeAccessor
,效果更好。但是,ToDataTable程序包的性能要好得多。
如果您使用的是VB.NET,则此类将完成此工作。
Imports System.Reflection
''' <summary>
''' Convert any List(Of T) to a DataTable with correct column types and converts Nullable Type values to DBNull
''' </summary>
Public Class ConvertListToDataset
Public Function ListToDataset(Of T)(ByVal list As IList(Of T)) As DataTable
Dim dt As New DataTable()
'/* Create the DataTable columns */
For Each pi As PropertyInfo In GetType(T).GetProperties()
If pi.PropertyType.IsValueType Then
Debug.Print(pi.Name)
End If
If IsNothing(Nullable.GetUnderlyingType(pi.PropertyType)) Then
dt.Columns.Add(pi.Name, pi.PropertyType)
Else
dt.Columns.Add(pi.Name, Nullable.GetUnderlyingType(pi.PropertyType))
End If
Next
'/* Populate the DataTable with the values in the Items in List */
For Each item As T In list
Dim dr As DataRow = dt.NewRow()
For Each pi As PropertyInfo In GetType(T).GetProperties()
dr(pi.Name) = IIf(IsNothing(pi.GetValue(item)), DBNull.Value, pi.GetValue(item))
Next
dt.Rows.Add(dr)
Next
Return dt
End Function
End Class
如果您的课程中有属性,那么这行代码就可以了!
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
但是,如果您拥有所有公共字段,请使用以下命令:
public static DataTable ToDataTable<T>( IList<T> data)
{
FieldInfo[] myFieldInfo;
Type myType = typeof(T);
// Get the type and fields of FieldInfoClass.
myFieldInfo = myType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance
| BindingFlags.Public);
DataTable dt = new DataTable();
for (int i = 0; i < myFieldInfo.Length; i++)
{
FieldInfo property = myFieldInfo[i];
dt.Columns.Add(property.Name, property.FieldType);
}
object[] values = new object[myFieldInfo.Length];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = myFieldInfo[i].GetValue(item);
}
dt.Rows.Add(values);
}
return dt;
}
原来的答案是从上面开始的,我只是编辑为使用字段而不是属性
并使用它来做到这一点
DataTable dt = new DataTable();
dt = ToDataTable(myBriefs);
gridData.DataSource = dt;
gridData.DataBind();
private DataTable CreateDataTable(IList<T> item)
{
Type type = typeof(T);
var properties = type.GetProperties();
DataTable dataTable = new DataTable();
foreach (PropertyInfo info in properties)
{
dataTable.Columns.Add(new DataColumn(info.Name, Nullable.GetUnderlyingType(info.PropertyType) ?? info.PropertyType));
}
foreach (T entity in item)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
将通用列表转换为DataTable
使用Newtonsoft.Json;
public DataTable GenericToDataTable(IList<T> list)
{
var json = JsonConvert.SerializeObject(list);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
return dt;
}
这是将列表转换为数据表的简单控制台应用程序。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ComponentModel;
namespace ConvertListToDataTable
{
public static class Program
{
public static void Main(string[] args)
{
List<MyObject> list = new List<MyObject>();
for (int i = 0; i < 5; i++)
{
list.Add(new MyObject { Sno = i, Name = i.ToString() + "-KarthiK", Dat = DateTime.Now.AddSeconds(i) });
}
DataTable dt = ConvertListToDataTable(list);
foreach (DataRow row in dt.Rows)
{
Console.WriteLine();
for (int x = 0; x < dt.Columns.Count; x++)
{
Console.Write(row[x].ToString() + " ");
}
}
Console.ReadLine();
}
public class MyObject
{
public int Sno { get; set; }
public string Name { get; set; }
public DateTime Dat { get; set; }
}
public static DataTable ConvertListToDataTable<T>(this List<T> iList)
{
DataTable dataTable = new DataTable();
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor propertyDescriptor = props[i];
Type type = propertyDescriptor.PropertyType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
type = Nullable.GetUnderlyingType(type);
dataTable.Columns.Add(propertyDescriptor.Name, type);
}
object[] values = new object[props.Count];
foreach (T iListItem in iList)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(iListItem);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
}
}
接受永久保护的理由
// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
Type Propiedad = null;
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
Propiedad = prop.PropertyType;
if (Propiedad.IsGenericType && Propiedad.GetGenericTypeDefinition() == typeof(Nullable<>))
{
Propiedad = Nullable.GetUnderlyingType(Propiedad);
}
table.Columns.Add(prop.Name, Propiedad);
}
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;
}
Dim counties As New List(Of County)
Dim dtCounties As DataTable
dtCounties = _combinedRefRepository.Get_Counties()
If dtCounties.Rows.Count <> 0 Then
For Each row As DataRow In dtCounties.Rows
Dim county As New County
county.CountyId = row.Item(0).ToString()
county.CountyName = row.Item(1).ToString().ToUpper()
counties.Add(county)
Next
dtCounties.Dispose()
End If
我认为它更方便易用。
List<Whatever> _lobj= new List<Whatever>();
var json = JsonConvert.SerializeObject(_lobj);
DataTable dt = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
最简单的答案可能是:
如果要使用反射并设置列顺序/仅包括一些列/排除一些列,请尝试以下操作:
private static DataTable ConvertToDataTable<T>(IList<T> data, string[] fieldsToInclude = null,
string[] fieldsToExclude = null)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
if ((fieldsToInclude != null && !fieldsToInclude.Contains(prop.Name)) ||
(fieldsToExclude != null && fieldsToExclude.Contains(prop.Name)))
continue;
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
foreach (T item in data)
{
var atLeastOnePropertyExists = false;
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
if ((fieldsToInclude != null && !fieldsToInclude.Contains(prop.Name)) ||
(fieldsToExclude != null && fieldsToExclude.Contains(prop.Name)))
continue;
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
atLeastOnePropertyExists = true;
}
if(atLeastOnePropertyExists) table.Rows.Add(row);
}
if (fieldsToInclude != null)
SetColumnsOrder(table, fieldsToInclude);
return table;
}
private static void SetColumnsOrder(DataTable table, params String[] columnNames)
{
int columnIndex = 0;
foreach (var columnName in columnNames)
{
table.Columns[columnName].SetOrdinal(columnIndex);
columnIndex++;
}
}