C# how to convert IEnumerable anonymous lists into data table

前端 未结 2 1377
别跟我提以往
别跟我提以往 2021-01-15 11:12

Many solutions are available that convert lists to DataTable that use reflection, and that would work for converting anonymous types. However, it there are

2条回答
  •  一整个雨季
    2021-01-15 11:32

    Improved on @MarcGravell's answer to support:

    1. An optional list of fields specifying which columns to keep and their order.
    2. Nullable types.

      static public DataTable ToDataTable(this IList anonymousSource, List keepOrderedFieldsOpt = null)
      {
          // https://stackoverflow.com/a/13153479/538763 - @MarcGravell
          // Added keepOrderedFieldsOpt, nullable types - @crokusek
      
          if (anonymousSource == null) throw new ArgumentNullException();
          DataTable table = new DataTable();
          if (anonymousSource.Count == 0) return table;
      
          // blatently assume the list is homogeneous
          Type itemType = anonymousSource[0].GetType();
          table.TableName = itemType.Name;            
      
          // Build up orderedColumns
          //
          List orderedColumns;            
          if (keepOrderedFieldsOpt != null)
          {
              Dictionary propertiesByName = itemType.GetProperties()
                  .ToDictionary(p => p.Name, p => p);
      
              orderedColumns = new List();
              List missingFields = null;
      
              foreach (string field in keepOrderedFieldsOpt)
              {
                  PropertyInfo tempPropertyInfo;
                  if (propertiesByName.TryGetValue(field, out tempPropertyInfo))
                      orderedColumns.Add(tempPropertyInfo);
                  else
                      (missingFields ?? (missingFields = new List())).Add(field);
              }
      
              if (missingFields != null) 
                  throw new ArgumentOutOfRangeException("keepOrderedFieldsOpt", "Argument keepOrderedFieldsOpt contains invalid field name(s): " + String.Join(", ", missingFields));
          }
          else
              orderedColumns = itemType.GetProperties().ToList();
      
          List names = new List();
          foreach (PropertyInfo prop in orderedColumns)
          {
              if (prop.CanRead && prop.GetIndexParameters().Length == 0)
              {
                  names.Add(prop.Name);
      
                  // Nullable support from stackoverflow.com/a/23233413/538763 - @Damith
                  table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
              }
          }
          names.TrimExcess();
      
          TypeAccessor accessor = TypeAccessor.Create(itemType);
          object[] values = new object[names.Count];
          foreach (var row in anonymousSource)
          {
              for (int i = 0; i < values.Length; i++)
                  values[i] = accessor[row, names[i]];
      
              table.Rows.Add(values);
          }
          return table;
      }
      

提交回复
热议问题