Thanks for sharing. I have a similar utility with additional capabilities that some of you might find useful.


using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.ComponentModel; using System.Reflection; namespace Examples public delegate T CreateObjectDelegate<T>(); public class ListHelper private ListHelper() public static DataTable ConvertTo<T>(List<T> list) DataTable table = CreateTable<T>(); Type entityType = typeof (T); PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType); object value = null ; DateTime dte = null ; foreach (T item in list) { DataRow row = table.NewRow(); foreach (PropertyDescriptor prop in properties) { value = prop.GetValue(item); if ( value != null ) { if (( value ) is DateTime) { dte = (DateTime) value ; if (dte == DateTime.MinValue) { row[prop.Name] = DBNull.Value; } else { row[prop.Name] = value ; } else { row[prop.Name] = prop.GetValue(item); } else { row[prop.Name] = DBNull.Value; table.Rows.Add(row); return table; public static List<T> ConvertTo<T>(List<DataRow> rows, CreateObjectDelegate<T> del) List<T> list = null ; if (rows != null ) { list = new List<T>(); foreach (DataRow row in rows) { T item = CreateItem<T>(row, del); list.Add(item); return list; public static List<T> ConvertTo<T>(List<DataRow> rows) List<T> list = null ; if (rows != null ) { list = new List<T>(); foreach (DataRow row in rows) { T item = CreateItem<T>(row); list.Add(item); return list; public static List<T> ConvertTo<T>(DataRow[] rows) List<T> list = null ; if (rows != null ) { list = new List<T>(); foreach (DataRow row in rows) { T item = CreateItem<T>(row); list.Add(item); return list; public static List<T> ConvertTo<T>(List<DataRow> rows, string sortString) List<T> list = null ; if (rows != null ) { list = new List<T>(); foreach (DataRow row in rows) { T item = CreateItem<T>(row); list.Add(item); GenericSorter<T> sorter = new GenericSorter<T>(sortString); list.Sort(sorter); return list; public static List<T> ConvertTo<T>(DataTable dt, string sortString) if (dt == null ) { return null ; List<DataRow> rows = new List<DataRow>(); foreach (DataRow row in dt.Rows) { rows.Add(row); return ConvertTo<T>(rows, sortString); public static List<T> ConvertTo<T>(DataTable dt) if (dt == null ) { return null ; List<DataRow> rows = new List<DataRow>(); foreach (DataRow row in dt.Rows) { rows.Add(row); return ConvertTo<T>(rows); public static List<T> ConvertTo<T>(DataTable dt, CreateObjectDelegate<T> del) if (dt == null ) { return null ; List<DataRow> rows = new List<DataRow>(); foreach (DataRow row in dt.Rows) { rows.Add(row); return ConvertTo<T>(rows, del); public static T CreateItem<T>(DataRow dr, CreateObjectDelegate<T> del) T obj = null ; if (dr != null ) { if (del != null ) { obj = del.Invoke(); } else { obj = Activator.CreateInstance<T>(); if (obj != null ) { foreach (DataColumn column in dr.Table.Columns) { PropertyInfo prop = obj.GetType().GetProperty(column.ColumnName); if (prop != null ) { if (!object.ReferenceEquals(dr[column.ColumnName], DBNull.Value)) { prop.SetValue(obj, dr[column.ColumnName], null ); } else { prop.SetValue(obj, null , null ); return obj; public static T CreateItem<T>(DataRow dr) T obj = null ; if (dr != null ) { obj = Activator.CreateInstance<T>(); if (obj != null ) { foreach (DataColumn column in dr.Table.Columns) { PropertyInfo prop = obj.GetType().GetProperty(column.ColumnName); if (prop != null ) { if (!object.ReferenceEquals(dr[column.ColumnName], DBNull.Value)) { prop.SetValue(obj, dr[column.ColumnName], null ); } else { prop.SetValue(obj, null , null ); return obj; public static DataTable CreateTable<T>() Type entityType = typeof (T); DataTable dt = new DataTable(entityType.Name); PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType); if (properties != null ) { foreach (PropertyDescriptor prop in properties) { dt.Columns.Add(prop.Name, prop.PropertyType); return dt; /// < summary > /// Sort order enumeration /// < /summary > public enum SortOrder Ascending, Descending /// < summary > /// Sorts a generic collection of some object /// Example: /// Dim MyList As List(Of MyClassType) = 'Populate the list somehow /// Dim Sorter As New Sorter(Of MyClassType) ''' Sorter.SortString = "Field1 DESC, Field2" /// MyList.Sort(Sorter) 'After this call, the list is sorted /// < /summary > public class GenericSorter<T> : IComparer<T> private string _sort; /// < summary > /// Instantiate the class. /// < /summary > public GenericSorter() /// < summary > /// Instantiate the class, setting the sort string. /// Example: "LastName DESC, FirstName" /// < /summary > public GenericSorter( string SortString) _sort = SortString; /// < summary > /// The sort string used to perform the sort. Can sort on multiple fields. /// Use the property names of the class and basic SQL Syntax. /// Example: "LastName DESC, FirstName" /// < /summary > public string SortString { get { if (_sort != null ) { return _sort.Trim(); return null ; set { _sort = value ; } /// < summary > /// This is an implementation of IComparer(Of T).Compare /// Can sort on multiple fields, or just one. /// < /summary > public int Compare(T x, T y) if (!string.IsNullOrEmpty( this .SortString)) { const string err = " The property \"{0}\" does not exist in type \"{1}\"" ; Type type = typeof (T); Comparer comp = Comparer.DefaultInvariant; PropertyInfo info = null ; foreach ( string expr in this .SortString.Split( ' ,' )) { SortOrder dir = SortOrder.Ascending; string field = null ; expr = expr.Trim(); if (expr.EndsWith( " DESC" )) { field = expr.Replace( " DESC" , string .Empty).Trim(); dir = SortOrder.Descending; } else { field = expr.Replace( " ASC" , string .Empty).Trim(); info = type.GetProperty(field); if (info == null ) { throw new MissingFieldException( string .Format(err, field, type.ToString())); } else { int Result = comp.Compare(info.GetValue(x, null ), info.GetValue(y, null )); if (Result != 0 ) { if (dir == SortOrder.Descending) { return Result * -1; } else { return Result; return 0 ;