How to convert a DataTable to a <T> list using reflections
I have a generic class list that I automatically convert to a DataTable using Reflection and extension methods. Now I want to do it in the opposite direction. I want to convert a DataTable to List.Better to say that I want to help write a method that expects a DataTable and Type , and automatically find the property of this type (class) according to the column name and assign a value to this type (class). For example, this psodu code:
private List<T> ConvertToList<T>(DataTable dt) { List<string> AllColumns = // Get All Column Names of a DataTable for(int i=0;i<dt.Rows.Count;i++) { foreach(var item in AllColumns ) { //Get Property According To **ITEM** //Get Data Of Rows[i][item] and assign it to T.property } } } How can i do this?
Change 1)
I am using @Cuong Le's answer as follows:
var properties = typeof(CustomType).GetProperties().ToList(); List<CustomType> list = ConvertToList<CustomType>(dt, properties); and:
private List<T> ConvertToList<T>(DataTable dt,List<PropertyInfo> fields) where T : class { return dt.AsEnumerable().Select(Convert<T>(fields)).ToList(); <------ } private T Convert<T>(DataRow row,List<PropertyInfo> fields) where T : class { var properties = typeof(T).GetProperties().ToList(); var objT = Activator.CreateInstance<T>(); foreach (var pro in properties) { pro.SetValue(objT, row[pro.Name],null); } return objT; } but in the line I will put an arrow in front of her. I got two errors:
No overload for 'Convert' method takes 1 argument
and
Type arguments to the method "System.Data.EnumerableRowCollectionExtensions.Select (System.Data.EnumerableRowCollection, System.Func)" cannot be taken out of use. Try explicitly specifying type arguments.
How can I solve this problem?
Use the AsEnumerable() method to support LINQ:
private List<T> ConvertToList<T>(DataTable dt) { var columnNames = dt.Columns.Cast<DataColumn>() .Select(c => c.ColumnName) .ToList(); var properties = typeof(T).GetProperties(); return dt.AsEnumerable().Select(row => { var objT = Activator.CreateInstance<T>(); foreach (var pro in properties) { if (columnNames.Contains(pro.Name)) pro.SetValue(objT, row[pro.Name]); } return objT; }).ToList(); }
GetPropertiessearches for properties of the current type using the specified binding constraints.
Link here: http://msdn.microsoft.com/en-us/library/kyaxdd3x.aspx