我正在尝试将列表转换为数据表。我已经完成了基本轮廓,但是只停留在一部分上。我试图只从类中获取一些属性。
public static DataTable ToDataTable<T>(this IList<T> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
table.Columns.Add("type", typeof(string));
table.Columns.Add("id", typeof(Int32));
table.Columns.Add("name", typeof(string));
table.Columns.Add("city", typeof(string));
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;
}
问题是,当到达第二个属性时,它抛出错误,指出列'unincludedCol'不属于表。
我该如何解决?
如果只需要类型,ID,名称和城市,则可以将它们添加到字符串列表中:
List<string> columnNames = new List<string>
{
"type","id","name","city"
};
或从dataTable
中提取它们,如:
List<string> columnNames = new List<string>();
foreach(DataColumn column in dataTable.Columns)
{
columnNames.Add(column.ColumnName);
}
并在循环中检查columnNames
是否包含prop.Name
,例如:
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
{
if(!columnNames.Contains(prop.Name))
continue;
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
table.Rows.Add(row);
}
注:代替if(!columnNames.Contains(prop.Name))
,可以使用.Any()
和Equals
方法忽略大小写:
if (!columnNames.Any(c => c.Equals(prop.Name, StringComparison.OrdinalIgnoreCase)))
continue;
希望您能找到帮助。
我相信使用属性是属性会更通用
[Attribute
[AttributeUsage(AttributeTargets.Property)]
public class UseAsTableColumn : Attribute
{
}
助手-更改了您的方法(使用属性名称作为列名称)
public static class Helper
{
public static DataTable ToDataTable<T>(this IList<T> data)
{
var mappableAttrirbs = typeof(T).GetProperties().Where(x => x.GetCustomAttributes(typeof(UseAsTableColumn), true).FirstOrDefault() != null);
DataTable table = new DataTable();
foreach (var property in mappableAttrirbs)
{
table.Columns.Add(property.Name, property.PropertyType);
}
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (var prop in mappableAttrirbs)
{
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
}
table.Rows.Add(row);
}
return table;
}
}
数据模型(要序列化的标记属性)
public class DataModel
{
[UseAsTableColumn]
public string Type { get; set; }
[UseAsTableColumn]
public int Id { get; set; }
[UseAsTableColumn]
public string Name { get; set; }
[UseAsTableColumn]
public string City { get; set; }
public string _InternalValue { get; private set; }
}
Runner
public class Program
{
static void Main(string[] args)
{
List<DataModel> data = new List<DataModel>()
{
new DataModel() { Type="Magic", Id= 1, Name = "foo", City = "bar" },
new DataModel() { Type="Magic", Id= 2, Name = "foo1", City = "bar1" }
};
Helper.ToDataTable(data);
Console.ReadKey();
}
}