I often revist my own code experiments when the need arises. This weekend at
pattern and if it suppoted multi-key sorts. I said no, but it could. The only
weakness is that it only supports Ascending sort order for the "extra" keys
beyond the first one. So, if you want to sort your data types in C# code, and
you want to produce results ala
then
this should work for you. Suppose you have a Type Foo:
Create some instances of type Foo to sort. In order to use the new
And last but not least, if you are actually interested in using this, here is
the code, only slight modifications from the old TypeComparer:
using
System;
using
System.Collections;
using
System.Reflection;
namespace
DamonPayne.Trap.Engine
{
/// <summary>
/// Make it easy to Sort Custom
Types
/// </summary>
public class TypeComparer :
IComparer
{
private delegate int DoCompare(object x, object
y);
private DoCompare
_compareMethod;
private PropertyInfo
_propInfo;
private Hashtable
_methods;
private bool
_caseSensitive;
private string
_sortProperty;
private bool
_multiField;
private PropertyInfo[]
_propInfos;
private DoCompare[]
_multiMethods;
public TypeComparer(string propertyName, Type
objectType)
{
_caseSensitive = true;
_sortProperty = propertyName;
_methods = BuildSortMethods();
_propInfo = objectType.GetProperty(_sortProperty);
if (null == _propInfo)
{
throw new ArgumentException(string.Format("Type {0} does
not have a Property '{1}'", new Object[] {objectType.ToString(),
propertyName}));
}
_compareMethod =
(DoCompare)_methods[_propInfo.PropertyType];
if (null == _compareMethod)
{
throw new ArgumentException( string.Format("Type not
supported: {0}", _propInfo.PropertyType) );
}
}
public TypeComparer(string[] names, Type
objectType)
{
_caseSensitive = true;
_multiField = true;
_sortProperty = names[0];
_methods = BuildSortMethods();
_propInfos = new
PropertyInfo[names.Length];
_multiMethods = new
DoCompare[names.Length];
for(int i = 0; i < names.Length;
++i)
{
_propInfos[i] = objectType.GetProperty(names[i]);
if (null == _propInfos[i])
{
throw new ArgumentException(string.Format("Type {0} does
not have a Property '{1}'", new Object[] {objectType.ToString(),
names[i]}));
}
_multiMethods[i] =
(DoCompare)_methods[_propInfos[i].PropertyType];
if (null == _multiMethods[i])
{
throw new ArgumentException( string.Format("Type not
supported: {0}", _propInfo.PropertyType) );
}
}
}
protected Hashtable
BuildSortMethods()
{
Hashtable ht = new
Hashtable();
ht.Add(typeof(int), new
DoCompare(CompareInt));
ht.Add(typeof(double), new
DoCompare(CompareDouble));
ht.Add(typeof(string), new
DoCompare(CompareString));
ht.Add(typeof(DateTime), new
DoCompare(CompareDate));
return
ht;
}
public bool
CaseSensitive
{
get{return
_caseSensitive;}
set{_caseSensitive = value;}
}
protected int CompareInt(object x, object y)
{
int xInt = (int)x;
int yInt = (int)y;
return
xInt.CompareTo(yInt);
}
protected int CompareDouble(object x, object
y)
{
double xDouble = (double)x;
double yDouble = (double)y;
return
xDouble.CompareTo(yDouble);
}
protected int CompareDate(object x, object y)
{
DateTime xDate = (DateTime)x;
DateTime yDate = (DateTime)y;
return
xDate.CompareTo(yDate);
}
protected int CompareString(object x, object y)
{
string xString = (string)x;
string yString = (string)y;
if (!CaseSensitive)
{
xString = xString.ToUpper();
yString = yString.ToUpper();
}
return
xString.CompareTo(yString);
}
#region IComparer
Members
public int Compare(object x, object y)
{
if (_multiField)
{
return
MultiKeyCompare(x, y);
}
object xVal =
_propInfo.GetValue(x, null);
object yVal =
_propInfo.GetValue(y, null);
return _compareMethod(xVal,
yVal);
}
public int MultiKeyCompare(object x, object y)
{
int index =
0;
object xVal = null;
object yVal = null;
int comp =
0;
while(0 == comp &&
index < _propInfos.Length)
{
xVal = _propInfos[index].GetValue(x, null);
yVal = _propInfos[index].GetValue(y, null);
comp = _multiMethods[index](xVal,yVal);
++index;
}
return
comp;
}
#endregion
}
}