thrashead thrashead - 2 months ago 39
C# Question

How can I bind a dataGridView object with dynamically created class list

I have an extension class method like below. It fills a list with dynamically created class object. When I try to bind a dataGridVew with it, it does not work.

Here's my extension method;

internal static List<dynamic> ToDynamicList(this DataTable _dataTable, string _className)
{
return ToDynamicList(ToDictionary(_dataTable), GetNewObject(_dataTable.Columns, _className));
}

private static List<Dictionary<string, object>> ToDictionary(DataTable _dataTable)
{
var columns = _dataTable.Columns.Cast<DataColumn>();
var Temp = _dataTable.AsEnumerable().Select(dataRow => columns.Select(column =>
new { Column = column.ColumnName, Value = dataRow[column] })
.ToDictionary(data => data.Column, data => data.Value)).ToList();
return Temp.ToList();
}

private static List<dynamic> ToDynamicList(List<Dictionary<string, object>> _list, Type _typeObj)
{
dynamic temp = new List<dynamic>();
foreach (Dictionary<string, object> step in _list)
{
object Obj = Activator.CreateInstance(_typeObj);

PropertyInfo[] properties = Obj.GetType().GetProperties();

Dictionary<string, object> DictList = (Dictionary<string, object>)step;

foreach (KeyValuePair<string, object> keyValuePair in DictList)
{
foreach (PropertyInfo property in properties)
{
if (property.Name == keyValuePair.Key)
{
if (keyValuePair.Value != null && keyValuePair.Value.GetType() != typeof(System.DBNull))
{
if (keyValuePair.Value.GetType() == typeof(System.Guid))
{
property.SetValue(Obj, keyValuePair.Value, null);
}
else
{
property.SetValue(Obj, keyValuePair.Value, null);
}
}
break;
}
}
}
temp.Add(Obj);
}
return temp;
}

private static Type GetNewObject(DataColumnCollection _columns, string _className)
{
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "YourAssembly";
System.Reflection.Emit.AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder module = assemblyBuilder.DefineDynamicModule("YourDynamicModule");
TypeBuilder typeBuilder = module.DefineType(_className, TypeAttributes.Public);

foreach (DataColumn column in _columns)
{
string propertyName = column.ColumnName;
FieldBuilder field = typeBuilder.DefineField(propertyName, column.DataType, FieldAttributes.Public);
PropertyBuilder property = typeBuilder.DefineProperty(propertyName, System.Reflection.PropertyAttributes.None, column.DataType, new Type[] { column.DataType });
MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;
MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_value", GetSetAttr, column.DataType, new Type[] { column.DataType }); // Type.EmptyTypes);
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_value", GetSetAttr, null, new Type[] { column.DataType });
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
}
Type obj = typeBuilder.CreateType();
return obj;
}


And here's my code that does not bind data grid view object;

dataGridView1.DataSource = dataTable.ToDynamicList("blabla");

Answer Source

The problem is not related to List<dynamic> or DataGridView, but a trivial error in this dynamic class builder line

MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_value", GetSetAttr, 
    column.DataType, new Type[] { column.DataType }); // Type.EmptyTypes);

Looks like you were playing with that code. Change it (back) to

MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_value", GetSetAttr,
   column.DataType, Type.EmptyTypes);

and the problem will be solved.