2016-04-20 22 views
0

我堅持以下問題:如何IEnumerable的<T>列表轉換爲數據表在C#中

我通常使用下面的功能自定義的數據傳輸到數據表,但在這種情況下,輸入數據是列表構成的一類。我只需要在DataTable中寫入每行每個列表的第一個元素。你能幫我調整這個功能來實現嗎?

public List<int> xID { get; set; } 
public List<string> xName { get; set; } 
public List<string> xType { get; set; } 
public List<string> xSource { get; set; } 
public List<int> xmdID { get; set; } 
public List<string> xMDName { get; set; } 
public List<string> xUser { get; set; } 

public static DataTable ListToDataTable<T>(IEnumerable<T> list) 
{ 
    Type type = typeof(T); 
    var properties = type.GetProperties(); 

    DataTable dataTable = new DataTable(); 
    foreach (PropertyInfo info in properties) 
    { 
     dataTable.Columns.Add(new DataColumn(info.Name, info.PropertyType)); 
    } 

    foreach (T entity in list) 
    { 
     object[] values = new object[properties.Length]; 
     for (int i = 0; i < properties.Length; i++) 
     { 
      values[i] = properties[i].GetValue(entity); 
     } 

     dataTable.Rows.Add(values); 
    } 

    return dataTable; 
} 

總部設在卡拉答案我想下面的代碼,但它不承認p-型類型(類型或命名空間名稱「的p-型」找不到(是否缺少using指令或程序集引用?))

var v = properties[i].GetValue(entity); 
Type pType = properties[i].PropertyType; 

if (pType.IsGenericType && pType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
pType = Nullable.GetUnderlyingType(pType); 

       if (pType.IsEnum) 
        pType = Enum.GetUnderlyingType(pType); 

       if (v.GetType().GetGenericTypeDefinition() == typeof(List<>)) 
       { 
        values[i] = (v as List<pType>).First(); 
       } 

UPDATE

我想這是不是最好的解決方案,因爲它不accep牛逼任何列表類型,但它是我能做的最好的:

public static DataTable ListToDataTable<T>(IEnumerable<T> list) 
    { 
     Type type = typeof(T); 
     var properties = type.GetProperties(); 

     DataTable dataTable = new DataTable(); 
     foreach (PropertyInfo info in properties) 
     { 
      Type propertyType = info.PropertyType; 

      if (propertyType.IsGenericType | propertyType.GetGenericTypeDefinition() == typeof(Nullable<>) | propertyType.IsEnum) 
       propertyType = propertyType.GetGenericArguments()[0]; 

      dataTable.Columns.Add(new DataColumn(info.Name, propertyType)); 
     } 

     foreach (T entity in list) 
     { 
      object[] values = new object[properties.Length]; 
      for (int i = 0; i < properties.Length; i++) 
      { 
       var v = properties[i].GetValue(entity); 
       Type pType = v.GetType().GetGenericArguments().FirstOrDefault(); 

       if (v.GetType().GetGenericTypeDefinition() == typeof(List<>)) 
       { 
        if(pType == typeof(int)) 
         values[i] = (v as List<int>).First(); 
        else if(pType == typeof(string)) 
         values[i] = (v as List<string>).First(); 
       } 
       else 
       { 
        values[i] = v; 
       } 
      } 
      dataTable.Rows.Add(values); 
     } 
     return dataTable; 
    } 
+2

如果你已經寫了這個,那麼它不能太難以至少試一試,對吧? – nvoigt

回答

0

你需要的東西是這樣的:

foreach (PropertyInfo info in properties) 
{ 
    if(info.PropertyType == typeof(IEnumerable)) 
    { 
     dataTable.Columns.Add(new DataColumn(info.Name, info.Cast<object>().First().GetType()); 
    } 
    else 
    { 
     dataTable.Columns.Add(new DataColumn(info.Name, info.PropertyType)); 
    } 
} 

foreach (T entity in list) 
{ 
    object[] values = new object[properties.Length]; 
    for (int i = 0; i < properties.Length; i++) 
    { 
     var v = properties[i].GetValue(entity); 
     if(v is IEnumerable) 
     { 
      values[i] = (v.Cast<object>().First()).First(); 
     } 
     else 
     { 
      values[i] = v; 
     } 
    } 

    dataTable.Rows.Add(values); 
} 
+0

編譯器無法識別.First();即使我添加「使用System.Linq」。 'System.Collections.IEnumerable'不包含'First'的定義,並且沒有找到接受'System.Collections.IEnumerable'類型的第一個參數的擴展方法'First'(你是否缺少using指令或程序集參考?) – Gabriel

+0

IEnumerable不支持Linq,可以將它轉換爲IEnumerable 以使用First。 – Carra

0

這對我的作品。我知道它here並修改它一點點。

public static DataTable ToDataTable<T>(this System.Collections.Generic.List<T> collection, string _sTableName) { 
     var table = new DataTable(_sTableName); 
     var type = typeof(T); 
     var properties = type.GetProperties(); 

     //Create the columns in the DataTable 
     foreach (var property in properties) { 
      if (property.PropertyType == typeof(int?)) { 
       table.Columns.Add(property.Name, typeof(int)); 
      } else if (property.PropertyType == typeof(decimal?)) { 
       table.Columns.Add(property.Name, typeof(decimal)); 
      } else if (property.PropertyType == typeof(double?)) { 
       table.Columns.Add(property.Name, typeof(double)); 
      } else if (property.PropertyType == typeof(DateTime?)) { 
       table.Columns.Add(property.Name, typeof(DateTime)); 
      } else if (property.PropertyType == typeof(Guid?)) { 
       table.Columns.Add(property.Name, typeof(Guid)); 
      } else if (property.PropertyType == typeof(bool?)) { 
       table.Columns.Add(property.Name, typeof(bool)); 
      } else { 
       table.Columns.Add(property.Name, property.PropertyType); 
      } 
     } 

     //Populate the table 
     foreach (var item in collection) { 
      var row = table.NewRow(); 
      row.BeginEdit(); 
      foreach (var property in properties) { 
       row[property.Name] = property.GetValue(item, null) ?? DBNull.Value; 
      } 

      row.EndEdit(); 
      table.Rows.Add(row); 
     } 

     return table; 
    } 
+0

類似這樣的檢查並不好。就像在你鏈接的例子中一樣,你應該使用'Nullable.GetUnderlyingType'方法來處理這些泛型的情況。 – thehennyy

+0

謝謝。其實它並沒有得到每個列表的第一個元素。結果與我發佈的代碼相同。 – Gabriel

+0

此代碼可以100%工作,現在已經生產了幾年。如果你沒有得到第一個項目,問題必須在其他地方。 –

相關問題