Preface
There are several cases when we feel the need to convert a List of objects into a DataTable
. There is a case where I particularly feel this need.
When we are using an object oriented approach in our web application, it is always better to bind the GridView
with a generic List of objects. The sorting of the GridView
becomes a problem in this case as the C# .NET Generic List class does not provide an easy sorting functionality.
Traditionally (the sorting solution for GridView
in almost all the .NET articles), we sort a GridView
by converting the source datatable
into a DataView
and binding the GridView
again with the sorted DataView
. This is a very easy method for GridView
sorting.
So, if we are binding GridView
with List of objects, we feel the need to convert it to a DataTable
at the time of sorting.
Since the generic class List
doesn’t provide a function to convert to DataTable
, I created a class ABList
which has this functionality.
Hence, one can use ABList
the same way as one will use List
, the only difference will be an additional function GetDataTable
.
I hope now I have justified the purpose of writing this article, so we can move forward to look at the working of ABList
.
Introduction
ABList
is a generic class which inherits System.Generics.Collections.List
. It adds a public
function GetDataTable
and thus extends its functionality to get a DataTable
containing all the public
properties as columns for the underlying class, and a row for each object in the List.
It can be used to create a List of any data type whether a reference type or value type. If the underlying type is a reference type, except String
, it will have columns same as all the public
properties of that class. If it is a value type, then only one column will be there called “Value
”, which will store the value of the variables in List
.
How to Use ABList Class
Using ABList
class is as simple as using a List
class. We need to define a variable by providing the underlying type we want to use with our ABList
class, as:
ABList<Product> lstP = new ABList<Product>();
Then we can add items to this list, as:
lstP.Add(new Product("a", "a"));
lstP.Add(new Product("b", "b"));
lstP.Add(new Product("c", "c"));
Just the way we do it with List
.
Now, if we want our List
to be converted into a DataTable
, we just need to call a new function defined in ABClass
:
DataTable dtPro = lstP.GetDataTable();
The ABList Class
The ABList
class is inheriting a generic class List
, it has only one function of its own, the GetDataTable
function. Following is the way ABList
has been defined:
public class ABList<T> : List<T>
Simple.
Then there is the GetDataTable
function. I have not constrained the ABList
for reference type or value type only. So we need to take care of both the cases while converting the List
into DataTable
as the underlying type can be both value or reference type.
First, we check how to get a DataTable
if the underlying type is a value type (or string
).
In value type, the DataTable
is expected to contain the values of all the variables (items) present in List
. Hence we create only one column in the DataTable
named “Value
”, and add a new row for each item found in the List
saving its value in the row.
if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
{
DataColumn dc = new DataColumn("Value");
dt.Columns.Add(dc);
foreach (T item in this)
{
DataRow dr = dt.NewRow();
dr[0] = item;
dt.Rows.Add(dr);
}
}
Though String
is a reference type, due to its behavior we treat it as a special case and handle it as value type only.
Now, for handling reference type, we need to make use of PropertyInfo
class of System.Reflection
namespace.
First, we find out all the public
properties of the underlying class using Reflection, as:
PropertyInfo[] piT = typeof(T).GetProperties();
So, we have all the public
properties of the underlying class, now we need to create a DataTable
and set column names to be property names in the array piT
.
foreach (PropertyInfo pi in piT)
{
DataColumn dc = new DataColumn(pi.Name, pi.PropertyType);
dt.Columns.Add(dc);
}
Then, we iterate through all the items in the List
and create a row for each item saving values of properties in the corresponding columns. To get the value of a property from the object (item), we need to call the GetValue
method for each property in our array of PropertyInfo piT
.
for (int item = 0; item < this.Count; item++)
{
DataRow dr = dt.NewRow();
for (int property = 0; property < dt.Columns.Count; property++)
{
dr[property] = piT[property].GetValue(this[item], null);
}
dt.Rows.Add(dr);
}
History
- 23rd May, 2010: Initial post