I'm trying to sort an array of objects with IComparer.
I wrote the code but it works only with the particular object. e.g.:
for this class
public class Cars
{
public string Name { get; set; }
public string Manufacturer { get; set; }
public int Year { get; set; }
public Cars(string name, string manufacturer, int year)
{
Name = name;
Manufacturer = manufacturer;
Year = year;
}
}
My code looks like:
class MySort
{
public class SortByYears : IComparer
{
int IComparer.Compare(Object x, Object y)
{
Cars X = (Cars)x, Y = (Cars)y;
return (X.Year.CompareTo(Y.Year));
}
}
public class SortByName : IComparer
{
int IComparer.Compare(Object x, object y)
{
Cars X = (Cars)x, Y = (Cars)y;
return (X.Name.CompareTo(Y.Name));
}
}
public class SortByManyfacturer : IComparer
{
int IComparer.Compare(object x, object y)
{
Cars X = (Cars)x, Y = (Cars)y;
return (X.Manufacturer.CompareTo(Y.Manufacturer));
}
}
}
But if I add another class with different properties it will be useless.
So is there any chance to modify this code so that it worked for objects with different properties?
class SortComparer<T> : IComparer<T>
{
private PropertyDescriptor PropDesc = null;
private ListSortDirection Direction =
ListSortDirection.Ascending;
public SortComparer(object item,string property,ListSortDirection direction)
{
PropDesc = TypeDescriptor.GetProperties(item)[property];
Direction = direction;
}
int IComparer<T>.Compare(T x, T y)
{
object xValue = PropDesc.GetValue(x);
object yValue = PropDesc.GetValue(y);
return CompareValues(xValue, yValue, Direction);
}
private int CompareValues(object xValue, object yValue,ListSortDirection direction)
{
int retValue = 0;
if (xValue is IComparable) // Can ask the x value
{
retValue = ((IComparable)xValue).CompareTo(yValue);
}
else if (yValue is IComparable) //Can ask the y value
{
retValue = ((IComparable)yValue).CompareTo(xValue);
}
// not comparable, compare String representations
else if (!xValue.Equals(yValue))
{
retValue = xValue.ToString().CompareTo(yValue.ToString());
}
if (direction == ListSortDirection.Ascending)
{
return retValue;
}
else
{
return retValue * -1;
}
}
}
Calling code:
Assuming a list named lst:
lst.Sort(new SortComparer<Cars>(lst[0],"YourPropertyName",ListSortDirection.Ascending));
You may leverage the Create method of Comparer<T> which takes a Comparison delegate and returns Comparer<T>.
var carnameComparer = Comparer<Cars>.Create((x, y) => x.Year.CompareTo(y.Year));
var carManufacturerComparer = Comparer<Cars>.Create((x, y) => x.Manufacturer.CompareTo(y.Manufacturer));
and for another type
var carsComparer = Comparer<SomeType>.Create((x, y) => x.SomeProperty.CompareTo(y.SomeProperty));
If you're in prior to .Net4.5 you can use the following CreateComparer method.
private static IComparer<T> CreateComparer<T>(Comparison<T> comparison)
{
return new ComparisonComparer<T>(comparison);
}
public class ComparisonComparer<T> : IComparer<T>
{
private Comparison<T> comparison;
public ComparisonComparer(Comparison<T> comparison)
{
if (comparison == null)
{
throw new ArgumentNullException("comparison");
}
this.comparison = comparison;
}
public int Compare(T x, T y)
{
return comparison(x, y);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With