If you've worked on creating a Data Access Layer you know how frustrating it can be to determine the type of data your DAL will be handling. For that reason, creating a converter that works with generics or vica-versa can be the long term answer.
Alright, so for our applications we have a couple of forms that use the DataGridView control to display tabular data (kinda of a common scenario for many business applications). The data is returned from our services as an IList<T> in which we can just then bind directly to the grid by using the grid's DataSource property. Pretty easy task...unless when it comes to data manipulations.
So, what we decided to was take the easy way out and that is convert our IList<T> to a DataTable object with the correct schema (for the primitive types) that our contained objects have. Here's what we came up with:
/// <summary>
/// Converts a data table to a list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataTable"></param>
/// <returns></returns>
public static IList<T> ConvertTo<T>(DataTable dataTable)
{
if (dataTable == null)
return null;
List<DataRow> Rows = new List<DataRow>();
foreach (DataRow row in dataTable.Rows)
{
Rows.Add(row);
}
return ConvertTo<T>(Rows);
}
/// <summary>
/// Create a object of the DataRow
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Row"></param>
/// <returns></returns>
public static T CreateItem<T>(DataRow Row)
{
T obj = default(T);
if (Row != null)
{
obj = Activator.CreateInstance<T>();
foreach (DataColumn column in Row.Table.Columns)
{
PropertyInfo property = obj.GetType().GetProperty(column.ColumnName);
try
{
object value = Row[column.ColumnName];
property.SetValue(obj, value, null);
}
catch
{
throw;
}
}
}
return obj;
}
/// <summary>
/// Converts a list of data row to List<T>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Rows"></param>
/// <returns></returns>
public static IList<T> ConvertTo<T>(IList<DataRow> Rows)
{
IList<T> Items = null;
if (Rows != null)
{
Items = new List<T>();
foreach (DataRow row in Rows)
{
T Item = CreateItem<T>(row);
Items.Add(Item);
}
}
return Items;
}
/// <summary>
/// Create a object of the DataRow
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Row"></param>
/// <returns></returns>
public static T CreateItem<T>(DataRow Row)
{
T obj = default(T);
if (Row != null)
{
obj = Activator.CreateInstance<T>();
foreach (DataColumn column in Row.Table.Columns)
{
PropertyInfo property = obj.GetType().GetProperty(column.ColumnName);
try
{
object value = Row[column.ColumnName];
property.SetValue(obj, value, null);
}
catch
{
throw;
}
}
}
return obj;
}