我正在尝试编写一个将 DataTable 转换为强类型对象列表的通用方法。
目前我使用的代码是...
public List<T> ImportTable<T>(String fileName, String table)
{
//Establish Connection to Access Database File
var mdbData = new ConnectToAccess(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\ACCESS\" + fileName + ".mdb;");
var tableData = new List<T>();
foreach (DataRow row in mdbData.GetData("SELECT * FROM " + table).Rows)
{
tableData.Add(ConvertRowToType<T>(row));
}
return tableData;
}
public T ConvertRowToType<T>(DataRow row)
{
//??? What is the best thing to do here ???
}
如果任何人的建议需要更改,我不会关注此代码。
假设我调用这个函数传递类型...
public class mdbConcern
{
public Int32 ConcernId { get; set; }
public String Concern { get; set; }
}
DataTable 中返回的数据看起来像...
ConcernID Concern
1 Law and Ethics
2 Mail
3 Business English
... ...
实现 ConvertRowToType(DataRow row) 方法的最佳方式是什么?
有人可以告诉我如何使用 Func 作为参数之一,以便我可以传递一些映射信息吗?
最佳答案
我认为扩展方法
是最好的方法:
public static class Helper
{
public static T ToType<T>(this DataRow row) where T : new()
{
T obj = new T();
var props = TypeDescriptor.GetProperties(obj);
foreach (PropertyDescriptor prop in props)
{
if(row.Table.Columns.IndexOf(prop.Name) >= 0
&& row[prop.Name].GetType() == prop.PropertyType)
{
prop.SetValue(obj, row[prop.Name]);
}
}
return obj;
}
}
用法:
public List<T> ImportTable<T>(String fileName, String table)
{
//Establish Connection to Access Database File
var mdbData = new ConnectToAccess(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\ACCESS\" + fileName + ".mdb;");
var tableData = new List<T>();
foreach (DataRow row in mdbData.GetData("SELECT * FROM " + table).Rows)
{
tableData.Add(row.ToType<T>());
}
return tableData;
}
更新 我看到您要求提供映射的 Func
。我不确定您的设想到底是什么,但这是我想出的一种方法:
public class mdbConcern
{
public Int32 ConcernId { get; set; }
public String Concern { get; set; }
public static PropertyDescriptor Mapping(string name)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(mdbConcern));
switch (name)
{
case "Concern_Id":
return props.GetByName("ConcernId");
case "Concern":
return props.GetByName("Concern");
default:
return null;
}
}
}
public static class Helper
{
public static T ToType<T>(this DataRow row, Func<string, PropertyDescriptor> mapping)
where T : new()
{
T obj = new T();
foreach (DataColumn col in row.Table.Columns)
{
var prop = mapping(col.ColumnName);
if(prop != null)
prop.SetValue(obj, row[col]);
}
return obj;
}
}
用法:
foreach (DataRow row in mdbData.GetData("SELECT * FROM " + table).Rows)
{
tableData.Add(row.ToType<mdbConcern>(mdbConcern.Mapping));
}
这是一个使用类型属性上的属性来存储其映射的版本。我认为这是一个更自然的解决方案:
[AttributeUsage(AttributeTargets.Property)]
public class ColumnMappingAttribute : Attribute
{
public string Name { get; set; }
public ColumnMappingAttribute(string name)
{
Name = name;
}
}
public class mdbConcern
{
ColumnMapping("Concern_Id")]
public Int32 ConcernId { get; set; }
ColumnMapping("Concern")]
public String Concern { get; set; }
}
public static class Helper
{
public static T ToType<T>(this DataRow row) where T : new()
{
T obj = new T();
var props = TypeDescriptor.GetProperties(obj);
foreach (PropertyDescriptor prop in props)
{
var columnMapping = prop.Attributes.OfType<ColumnMappingAttribute>().FirstOrDefault();
if(columnMapping != null)
{
if(row.Table.Columns.IndexOf(columnMapping.Name) >= 0
&& row[columnMapping.Name].GetType() == prop.PropertyType)
{
prop.SetValue(obj, row[columnMapping.Name]);
}
}
}
return obj;
}
}
关于c# - 将 DataTable 转换为强类型对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9199473/