2013-10-17 39 views
0

您好,我有以下方法。将对象列表转换为Datatable时出错

public static DataTable ConvertToDataTable<T>(List<T> lstData) 
{ 
    PropertyDescriptorCollection objPropertiesCollection = TypeDescriptor.GetProperties(typeof(T)); 
    DataTable dtResult = new DataTable(); 

    foreach (PropertyDescriptor objProperty in objPropertiesCollection) 
    { 
     dtResult.Columns.Add(objProperty.Name, Nullable.GetUnderlyingType(objProperty.PropertyType) ?? objProperty.PropertyType); 
    } 

    foreach (T item in lstData) 
    { 
     DataRow dr = dtResult.NewRow(); 

     foreach (PropertyDescriptor objProperty in objPropertiesCollection) 
     { 
      dr[objProperty.Name] = objProperty.GetValue(item) ?? DBNull.Value; 
     } 

     dtResult.Rows.Add(dr); 
    } 

    return dtResult; 
} 

和我有以下类

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace ClientesPagos.Clases 
{ 
    [Serializable] 
    public class Servicio 
    { 
     public int IdServicio; 
     public string Nombre; 
     public string Descripcion; 
     public string Imagen; 
     public decimal Precio; 
     public int Cantidad; 
     public decimal Total; 

     public Servicio() 
     { 

     } 

     public Servicio(int id, string nombre, string descripcion, string img, decimal precio, int cantidad) 
     { 
      IdServicio = id; 
      Nombre = nombre; 
      Descripcion = descripcion; 
      Imagen = img; 
      Precio = precio; 
      Cantidad = cantidad; 
      Total = cantidad * precio; 
     } 
    } 
} 

现在的问题是在方法的第一行

PropertyDescriptorCollection objPropertiesCollection = 
    TypeDescriptor.GetProperties(typeof(T)); 

它不填充objPropertiesCollection,因此下面的说明不要工作。

该类有什么问题,它可能不会在第一个方法上工作?

+2

Properties!= Fields。 –

+0

是否有任何特定的原因不使用CopyToDataTable();.我认为这会有所帮助 –

回答

2

您正在尝试获取属性,您应该将字段更改为属性。 这些属性:

public int IdServicio {get; set;} 
public string Nombre { get; set; } 
public string Descripcion { get; set; } 
public string Imagen { get; set; } 
public decimal Precio { get; set; } 
public int Cantidad { get; set; } 
public decimal Total { get; set; } 
0

所以你想转换“所有”到DataTable?然后我会在MSDN上使用CopyToDataTable的方法,它的ObjectShredder类。与任何一种IEnumerable<T>(即使匿名类型)的

public static class CustomLINQtoDataSetMethods { 
    public static DataTable CopyToDataTable<T>(this IEnumerable<T> source) { 
     return new ObjectShredder<T>().Shred(source, null, null); 
    } 

    public static DataTable CopyToDataTable<T>(this IEnumerable<T> source, 
               DataTable table, LoadOption? options) { 
     return new ObjectShredder<T>().Shred(source, table, options); 
    } 
} 

现在CopyToDataTable作品不仅具有DataRows

How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow

public class ObjectShredder<T> { 
    private System.Reflection.FieldInfo[] _fi; 
    private System.Reflection.PropertyInfo[] _pi; 
    private System.Collections.Generic.Dictionary<string, int> _ordinalMap; 
    private System.Type _type; 

    // ObjectShredder constructor. 
    public ObjectShredder() { 
     _type = typeof(T); 
     _fi = _type.GetFields(); 
     _pi = _type.GetProperties(); 
     _ordinalMap = new Dictionary<string, int>(); 
    } 

    /// <summary> 
    /// Loads a DataTable from a sequence of objects. 
    /// </summary> 
    /// <param name="source">The sequence of objects to load into the DataTable.</param> 
    /// <param name="table">The input table. The schema of the table must match that 
    /// the type T. If the table is null, a new table is created with a schema 
    /// created from the public properties and fields of the type T.</param> 
    /// <param name="options">Specifies how values from the source sequence will be applied to 
    /// existing rows in the table.</param> 
    /// <returns>A DataTable created from the source sequence.</returns> 
    public DataTable Shred(IEnumerable<T> source, DataTable table, LoadOption? options) { 
     // Load the table from the scalar sequence if T is a primitive type. 
     if (typeof(T).IsPrimitive) { 
      return ShredPrimitive(source, table, options); 
     } 

     // Create a new table if the input table is null. 
     if (table == null) { 
      table = new DataTable(typeof(T).Name); 
     } 

     // Initialize the ordinal map and extend the table schema based on type T. 
     table = ExtendTable(table, typeof(T)); 

     // Enumerate the source sequence and load the object values into rows. 
     table.BeginLoadData(); 
     using (IEnumerator<T> e = source.GetEnumerator()) { 
      while (e.MoveNext()) { 
       if (options != null) { 
        table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options); 
       } else { 
        table.LoadDataRow(ShredObject(table, e.Current), true); 
       } 
      } 
     } 
     table.EndLoadData(); 

     // Return the table. 
     return table; 
    } 

    public DataTable ShredPrimitive(IEnumerable<T> source, DataTable table, LoadOption? options) { 
     // Create a new table if the input table is null. 
     if (table == null) { 
      table = new DataTable(typeof(T).Name); 
     } 

     if (!table.Columns.Contains("Value")) { 
      table.Columns.Add("Value", typeof(T)); 
     } 

     // Enumerate the source sequence and load the scalar values into rows. 
     table.BeginLoadData(); 
     using (IEnumerator<T> e = source.GetEnumerator()) { 
      Object[] values = new object[table.Columns.Count]; 
      while (e.MoveNext()) { 
       values[table.Columns["Value"].Ordinal] = e.Current; 

       if (options != null) { 
        table.LoadDataRow(values, (LoadOption)options); 
       } else { 
        table.LoadDataRow(values, true); 
       } 
      } 
     } 
     table.EndLoadData(); 

     // Return the table. 
     return table; 
    } 

    public object[] ShredObject(DataTable table, T instance) { 

     FieldInfo[] fi = _fi; 
     PropertyInfo[] pi = _pi; 

     if (instance.GetType() != typeof(T)) { 
      // If the instance is derived from T, extend the table schema 
      // and get the properties and fields. 
      ExtendTable(table, instance.GetType()); 
      fi = instance.GetType().GetFields(); 
      pi = instance.GetType().GetProperties(); 
     } 

     // Add the property and field values of the instance to an array. 
     Object[] values = new object[table.Columns.Count]; 
     foreach (FieldInfo f in fi) { 
      values[_ordinalMap[f.Name]] = f.GetValue(instance); 
     } 

     foreach (PropertyInfo p in pi) { 
      values[_ordinalMap[p.Name]] = p.GetValue(instance, null); 
     } 

     // Return the property and field values of the instance. 
     return values; 
    } 

    public DataTable ExtendTable(DataTable table, Type type) { 
     // Extend the table schema if the input table was null or if the value 
     // in the sequence is derived from type T.    
     foreach (FieldInfo f in type.GetFields()) { 
      if (!_ordinalMap.ContainsKey(f.Name)) { 
       // Add the field as a column in the table if it doesn't exist 
       // already. 
       DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name] 
        : table.Columns.Add(f.Name, f.FieldType); 

       // Add the field to the ordinal map. 
       _ordinalMap.Add(f.Name, dc.Ordinal); 
      } 
     } 
     foreach (PropertyInfo p in type.GetProperties()) { 
      if (!_ordinalMap.ContainsKey(p.Name)) { 
       // Add the property as a column in the table if it doesn't exist 
       // already. 
       DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name] 
        : table.Columns.Add(p.Name, p.PropertyType); 

       // Add the property to the ordinal map. 
       _ordinalMap.Add(p.Name, dc.Ordinal); 
      } 
     } 

     // Return the table. 
     return table; 
    } 
} 

现在你可以添加这些扩展。

相关问题