have made a class using Generic that sorts any custom type collection based
on the selected property. When sorting on "PageName" it works fine, but when
sorting on "Index" I get Null Reference Exeption. Hope some smart guru can
help me out !!! :)
public class MyPageData : Dictionary<String, object>
{
private string pageName;
public string PageName
{
get {
if (pageName == null)
{
pageName = (string)this["PageName"] ?? "";
}
return pageName; }
}
}
protected void Page_Load(object sender, EventArgs e)
{
List<MyPageData> myPageDataCollection = new List<MyPageData>();
MyPageData page = new MyPageData();
page.Add("PageName", "John");
page.Add("Index", 1);
myPageDataCollection.Add(page);
page = new MyPageData();
page.Add("PageName", "Elizabeth");
page.Add("Index", 7);
myPageDataCollection.Add(page);
page = new MyPageData();
page.Add("PageName", "Paul");
page.Add("Index", 10);
myPageDataCollection.Add(page);
page = new MyPageData();
page.Add("PageName", "Andrew");
page.Add("Index", 4);
myPageDataCollection.Add(page);
foreach (MyPageData _page in myPageDataCollection)
{
Response.Write(_page.PageName + "<br/>");
}
Response.Write("Sorted list?<br/>");
myPageDataCollection.Sort(new GenericComparer<MyPageData>("PageName",
GenericComparer<MyPageData>.SortOrder.Ascending));
foreach (MyPageData _page in myPageDataCollection)
{
Response.Write(_page.PageName + "<br/>");
}
}
---------------------------------------------
This Works:
---------------------------------------------
myPageDataCollection.Sort(new GenericComparer<MyPageData>("PageName",
GenericComparer<MyPageData>.SortOrder.Ascending));
---------------------------------------------
This fails: (Null reference exeption)
---------------------------------------------
myPageDataCollection.Sort(new GenericComparer<MyPageData>("Index",
GenericComparer<MyPageData>.SortOrder.Ascending));
/// <summary>
/// This class is used to compare any
/// type(property) of a class for sorting.
/// This class automatically fetches the
/// type of the property and compares.
/// </summary>
public sealed class GenericComparer<T> : IComparer<T>
{
public enum SortOrder { Ascending, Descending };
#region member variables
private string sortColumn;
private SortOrder sortingOrder;
#endregion
#region constructor
public GenericComparer(string sortColumn, SortOrder sortingOrder)
{
this.sortColumn = sortColumn;
this.sortingOrder = sortingOrder;
}
#endregion
#region public property
/// <summary>
/// Column Name(public property of the class) to be sorted.
/// </summary>
public string SortColumn
{
get { return sortColumn; }
}
/// <summary>
/// Sorting order.
/// </summary>
public SortOrder SortingOrder
{
get { return sortingOrder; }
}
#endregion
#region public methods
/// <summary>
/// Compare interface implementation
/// </summary>
/// <param name="x">custom Object</param>
/// <param name="y">custom Object</param>
/// <returns>int</returns>
public int Compare(T x, T y)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(sortColumn);
IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);
if (sortingOrder == SortOrder.Ascending)
{
return (obj1.CompareTo(obj2));
}
else
{
return (obj2.CompareTo(obj1));
}
}
#endregion
}
Marc Gravell - 27 Mar 2008 16:51 GMT
Because MyPageData doesn't have an Index property - so:
typeof(T).GetProperty(sortColumn);
=
typeof(MyPageData).GetProperty("Index")
will be null.
You could probably tweak it to be a comparer of dictionaries, and getting
the value directly out of the dictionary? I'm loathe to put code to it,
though, as I'm not sure that this is the best overall approach...
Marc