通过使用反射和linq到对象的数据表 [英] Datatable to object by using reflection and linq
问题描述
我有一个这样的数据表
Name| Value
----|------
NA | VA
NB | VB
NC | VC1
NC | VC2
ND | VD1
ND | VD2
和这样的类
Class NVMapping {
List<string> NC { get; set; }
List<string> ND { get; set; }
string NA { get; set; }
string NB { get; set; }
}
如何使用linq或其他方式将数据表转换为此类型?
How to use linq or other way to transfer the datatable to this type ?
我认为我需要在这里强调一件事.这种映射将在我的应用程序中很多.
I think I need to emphasize one thing here. This kinda mapping will be a lot in my application.
我认为使用反射可以使此函数具有通用性来处理所有这些映射.
Somehow I think using reflection can make this function be generic to handle all these kinda mapping.
因此,如果可能的话,我更喜欢使用反射等通用功能来实现这一目标.
So if possible, I would prefer a generic function like using reflection to achieve this.
如果可能的话,最好像上面的转换一样将数据表传输到对象中.
If possible, it will even better just transfering datatable into an object like above transformation.
谢谢!
推荐答案
我可以建议编写一个使用反射的通用方法.以下方法使用反射从DataTable中的DataRow(或类的List<>,从DataTable中的每个DataRow中的一个)填充类的公共属性,其中ColumnName与类中公共属性的名称完全匹配(大小写-敏感的). 如果DataTable的额外列与该类中的属性不匹配,则将其忽略.如果DataTable缺少与类属性匹配的列,则将忽略该属性并将其保留为该类型的默认值(因为它是一个属性).
May I suggest writing a generic method that uses reflection. The following method uses reflection to populate a class's public properties from a DataRow in a DataTable (or a List<> of classes, one from each DataRow in the DataTable) where the ColumnName matches the name of the public property in the class exactly (case-sensitive). If the DataTable has extra columns that don't match up to a property in the class, they are ignored. If the DataTable is missing columns to match a class property, that property is ignored and left at the default value for that type (since it is a property).
public static IList<T> DatatableToClass<T>(DataTable Table) where T : class, new()
{
if (!Helper.IsValidDatatable(Table))
return new List<T>();
Type classType = typeof(T);
IList<PropertyInfo> propertyList = classType.GetProperties();
// Parameter class has no public properties.
if (propertyList.Count == 0)
return new List<T>();
List<string> columnNames = Table.Columns.Cast<DataColumn>().Select(column => column.ColumnName).ToList();
List<T> result = new List<T>();
try
{
foreach (DataRow row in Table.Rows)
{
T classObject = new T();
foreach (PropertyInfo property in propertyList)
{
if (property != null && property.CanWrite) // Make sure property isn't read only
{
if (columnNames.Contains(property.Name)) // If property is a column name
{
if (row[property.Name] != System.DBNull.Value) // Don't copy over DBNull
{
object propertyValue = System.Convert.ChangeType(
row[property.Name],
property.PropertyType
);
property.SetValue(classObject, propertyValue, null);
}
}
}
}
result.Add(classObject);
}
return result;
}
catch
{
return new List<T>();
}
}
如果您想采用其他方法,并从类的公共属性中填写数据表,请在我的C#博客
If you interested in going the other way, and fill out a DataTable from a class's public properties, I cover that and more on my C# blog, CSharpProgramming.tips/Class-to-DataTable
这篇关于通过使用反射和linq到对象的数据表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!