|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionA great article by Ryan Beesley on this site demonstrates how to sort a collection of objects using multiple BackgroundBasically, implementing sort on a collection requires two actions:
The problem with this approach is that you have to create as much classes than there are properties to compare. Using Reflection allows you to create only one comparer class which will manage all possibilities! Using the codeFirst, we will create a collection, and the multiple objects that this collection will hold. I've used the same architecture that Ryan Beesley used in his article, so you can easily compare the two techniques. So we will have fruits (Apple, Banana, and Cantaloupe), which will have three properties: Here is the code for public class Fruit
{
public virtual float Mass
{
get { return (float.NaN); }
}
public virtual string Color
{
get { return (null); }
}
public virtual string Name
{
get { return (string.Empty ); }
}
public class Banana : Fruit
{
public override float Mass
{
get { return (92.0f); }
}
public override string Color
{
get { return ("Yellow"); }
}
public override string Name
{
get { return ("Banana"); }
}
}
A collection of fruits will be implemented like this: public FruitBasket : CollectionBase
{
/// <sumary>
/// Get or set the <see cref='Fruit'/> at the specified index
/// </sumary>
/// <value></value>
public virtual Fruit this[int index]
{
get { return (Fruit) List[index]; }
set { List[index] = value; }
}
/// <sumary>
/// Add the specified Fruit to the collection
/// </sumary>
/// <param name='value'>Value.</param>
/// <returns></returns>;
public virtual int Add(Fruit value)
{
return List.Add(value);
}
And now, as seen in the Background section, we have to do two steps to implement sorting. First, create a class which implements the public enum SortOrderEnum
{
Ascending,
Descending
}
public class GenericComparer : IComparer
{
private String _Property = null;
private SortOrderEnum _SortOrder = SortOrderEnum.Ascending;
public String SortProperty
{
get { return _Property; }
set { _Property = value; }
}
public SortOrderEnum SortOrder
{
get { return _SortOrder; }
set { _SortOrder = value; }
}
public int Compare(object x, object y)
{
Fruit ing1;
Fruit ing2;
if (x is Fruit)
ing1 = (Fruit) x;
else
throw new ArgumentException("Object is not of type Fruit");
if (y is Fruit)
ing2 = (Fruit) y;
else
throw new ArgumentException("Object is not of type Fruit");
if (this.SortOrder.Equals(SortOrderEnum.Ascending))
return ing1.CompareTo(ing2, this.SortProperty);
else
return ing2.CompareTo(ing1, this.SortProperty);
}
}
As you can see, the comparer object calls the public int CompareTo(object obj, string Property)
{
try
{
Type type = this.GetType();
PropertyInfo propertie = type.GetProperty(Property);
Type type2 = obj.GetType();
PropertyInfo propertie2 = type2.GetProperty(Property);
object[] index = null;
object Obj1 = propertie.GetValue(this, index);
object Obj2 = propertie2.GetValue(obj, index);
IComparable Ic1 = (IComparable) Obj1;
IComparable Ic2 = (IComparable) Obj2;
int returnValue = Ic1.CompareTo(Ic2);
return returnValue;
}
catch (Exception Ex)
{
throw new ArgumentException("CompareTo is not possible !");
}
}
The last thing to do is to implement the public void Sort(String SortBy, SortOrderEnum SortOrder)
{
GenericComparer comparer = new GenericComparer();
comparer.SortProperty = SortBy;
comparer.SortOrder = SortOrder;
this.InnerList.Sort(comparer);
}
You have now a fully working collection that we can sort on all properties, with no need to add code when we add a property. Using the code:FruitBasket FB = new FruitBasket() ;
Fruit.Banana banana = new Fruit.Banana() ;
FB.Add(banana);
Fruit.Apple apple = new Fruit.Apple() ;
FB.Add(apple);
Fruit.Cantaloupe cantaloupe = new Fruit.Cantaloupe() ;
FB.Add(cantaloupe);
Sorting on name: FB.Sort("Name",SortOrderEnum.Ascending );
foreach(Fruit fruit in FB)
{
tvwDemo.Nodes.Add( " " + fruit.Name );
}
ConclusionI haven't compared the time required for sorting on hundreds of objects, but we can assume that the generic History
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||