A Coder's Blog
I wanted to add an extension method to a generic list to convert it into a datatable in order to be used as input param in a Stored Procedure
public static DataTable ConvertToDataTable<T>(this List<T> myList)
{
DataTable dt = new DataTable();
var allProperties = typeof(T).GetProperties().ToList();
//add all the columns
allProperties.ForEach(x => dt.Columns.Add(x.Name));
myList.ForEach(x =>
{
var row = dt.NewRow();
var type = x.GetType();
allProperties.ForEach(y =>
{
var propValue = type.GetProperty(y.Name).GetValue(x, null);
//example: if I want to convert a boolean into a BIT
ConversionAttr conversionType = y.GetCustomAttributes(typeof(ConversionAttr), false).FirstOrDefault() as ConversionAttr;
row[y.Name] = (propValue != null && conversionType != null) ? Convert.ChangeType(propValue, conversionType.ConversionType) : propValue;
});
dt.Rows.Add(row);
});
return dt;
}
You can use a custom attribute for conversion, let’s say that for example you want to convert a bool into an int
public class ConversionAttribute : Attribute
{
public Type ConversionType { get; set; }
public ConversionAttribute(Type type)
{
this.ConversionType = type;
}
}
Test it..
List<Test> t = new List<Test> { new Test { IsValid = true, Description = "This is a test" } };
DataTable dt = t.ConvertToDataTable<Test>();
//....
public class Test
{
[ConversionAttr(ConversionType = typeof(int))]
public bool IsValid { get; set; }
public string Description { get; set; }
//etc..
}
I also wrote this simple method that can be useful in case you want to convert a datarow (returned by a SP) into a specific object..
public static T ConvertToObject<T>(this DataRow dr)
{
var instance = Activator.CreateInstance<T>();
for (int i = 0; i < dr.Table.Columns.Count; i++)
{
var prop = instance.GetType().GetProperty(dr.Table.Columns[i].ColumnName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (prop != null)
prop.SetValue(instance, Convert.ChangeType(dr[i], prop.PropertyType));
}
return instance;
}
//...
//var test = dataRow.ConvertToObject<Test>();