The same way you used Reflection
to recover generic type properties, you can also use Reflection
to recover the value of the property for an instance of that type, it would look like this:
protected virtual DataTable buildDataTableFromComplexTypeList<T>(string tableName, List<T> complexList)
{
DataTable dataTable = new DataTable(tableName);
PropertyInfo[] properties = typeof(T).GetProperties(); // Getting the metadata through reflection (System.Reflection)
foreach (PropertyInfo property in properties) // Create DataTableColumns from the T properties
{
var type = (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(property.PropertyType) : property.PropertyType);
dataTable.Columns.Add(property.Name, type);
}
DataRow dataRow;
foreach (T item in complexList)
{
dataRow = dataTable.NewRow(); // Create new DataRow with the same columns of DataTable
// novas linhas
foreach (PropertyInfo property in properties)
dataRow[property.Name] = property.GetValue(item) ?? DBNull.Value;
dataTable.Rows.Add(dataRow);
}
// nova linha
return dataTable;
}
If you want, you can do the same using Linq
protected virtual DataTable buildDataTableFromComplexTypeList<T>(string tableName, List<T> complexList)
{
DataTable tabela = new DataTable();
PropertyInfo[] propriedades = typeof(T).GetProperties();
tabela.Columns.AddRange(
propriedades.Select(p => new DataColumn(p.Name, (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(p.PropertyType) : p.PropertyType))).ToArray()
);
complexList.ForEach(
i => tabela.Rows.Add(
propriedades.Select(p => p.GetValue(i) ?? DBNull.Value).ToArray()
)
);
return tabela;
}
I adjusted the answer with the placement of @Jeferson Almeida on Nullable
because I remember I’ve had problems with that in the past.
Sources:
Get Property value from string using Reflection in C#
LINQ: IENUMERABLE TO DATATABLE
I didn’t understand the need to check if it is
Nullable
– Matheus Saraiva
@Matheussaraiva For example, if your field is a
int
or adatetime
and vc trying to set a null value on them will give error, because these fields by default do not accept null values unless they are declared asNullable
and when you check only the type does not inform if that field accepts it– Jeferson Almeida
@Jefersonalmeida well observed on
Nullable
(adjusted my answer, I hope you don’t mind), but to fill in what isnull
in theDataRow
have to useDBNull.Value
or else you’ll be mistaken.– mateusalxd
Ok, I understood in the code of Xará @Mateus. Is that in your example the variable
var type
is not used. Thanks for the observation about the possibility of being nullable.– Matheus Saraiva
@Matheussaraiva was wrong, I forgot to use it, I’ll adjust my code
– Jeferson Almeida