我创建了通用List并填充了一些对象。然后我在前面提到的List转换为DataTable以在DataGridView中使用。问题是,当我想从这个网格获取Row时,我有DataRow。我想把它转换成我的对象,但不知道该怎么做。也许你可以举一些例子?
由于
答案 0 :(得分:11)
好吧,如果您不能或不会使用“ORM”(对象关系映射器,如Linq-to-SQL或NHibernate - 这正是这些工具所做的,并为您做得很好),我必须自己做。
将DataRow转换为域对象模型是非常无聊的代码,实际上是:
public Customer ConvertRowToCustomer(DataRow row)
{
Customer result = new Customer();
result.ID = row.Field<int>("ID");
result.Name = row.Field<string>("CustomerName");
..... // and so on
return result;
}
这里最大的挑战是使这个坚如磐石并处理(或避免)所有可能的错误(如字段为NULL等)。
另一种可能性是在域模型对象类型上有一个构造函数,它将DataRow
作为参数并从中构造一个新对象。
马克
答案 1 :(得分:8)
假设您正在使用类MyObject
,定义如下:
class MyObject
{
public string Foo { get; set; }
public int Foo { get; set; }
}
你可以这样做:
using System.Data.DataSetExtensions;
...
List<MyObject> list = (from row in table.AsEnumerable()
select new MyObject
{
Foo = row.Field<string>("foo"),
Bar = row.Field<int>("bar")
}).ToList();
答案 2 :(得分:1)
为什么不将对象放入BindingList&lt;&gt;而不是List&lt;&gt;?然后,您可以跳过转换为DataTable并再次返回练习。您可能需要在对象上实现 INotifyPropertyChanged ,但一旦它们位于BindingList中,datagrid中的更改将自动应用于您的基础对象。
可以通过在列标题单击上手动排序列表,或通过继承BindingList&lt;&gt;来处理排序。并在其中实现排序功能 - 然后单击标题会自动对列表进行排序 - 无需代码。
答案 3 :(得分:0)
现在使用ORM更容易。但是,如果您仍然使用旧时尚,您可以使用一个非常简单的扩展类来为您完成这项工作,使用一些反射和泛型方法和lambda如下:
public static class MapperExtensionClass
{
public static IEnumerable<MyClassType> ToMyClassTypeEnumerable(this DataTable table)
{
return table.AsEnumerable().Select(r => r.ToMyClassType());
}
public static MyClassType ToMyClassType(this DataRow row)
{
return row.ToObject<MyClassType>();
}
public static T ToObject<T>(this DataRow row) where T: new()
{
T obj = new T();
foreach (PropertyInfo property in typeof(T).GetProperties())
{
if (row.Table.Columns.Contains(property.Name))
{
property.SetValue(obj, property.PropertyType.ToDefault(row[property.Name]));
}
}
return obj;
}
public static object ToDefault(this Type type, object obj)
{
if (type == null)
throw new Exception("Customized exception message");
var method = typeof(MapperExtensionClass)
.GetMethod("ToDefaultGeneric", BindingFlags.Static | BindingFlags.Public);
var generic = method.MakeGenericMethod(type);
return generic.Invoke(null, new object[] { obj });
}
public static T ToDefaultGeneric<T>(object obj)
{
if (obj == null || obj == DBNull.Value)
{
return default(T);
}
else
{
return (T)obj;
}
}
}
您还应该记住GridView对象可以绑定很多数据源类型。所以从设计角度决定你应该采用什么。