Ordenar colecciones de objetos en base a sus propiedades
El uso de las colecciones para guardar objetos resulta sencillo, práctico y escalable. Es sencillo porque la lógica de una colección ya está definida por la plataforma; las operaciones básicas como agregar, eliminar, buscar y ordenar ya están definidas y son transparentes para su uso. También es práctico porque entre sus usos podemos asignarla a cualquier elemento en una interfaz que sea capaz de recibir una fuente de datos (DataSouirce) como un GridView, un DataList o un Repeater. Finalmente es escalable porque también podemos extender su funcionalidad para adaptar nuestra colección por ejemplo a que sea capaz de ordenarse en un Gridview en base la propiedad SortingExpression de un DataBoundFIeld.
Para ordenar una colección de objetos en base a alguna de sus propiedades tenemos que crear nuestro propio Comparador y para ellos utilizaremos la interfaz IComparer que a grandes rasgos nos permitirá personalizar el ordenamiento para nuestra colección. Finalmente será necesario utilizar dos namespace adicionales System.Collections.Generic y System.ComponentModel, este último nos permite buscar propiedades de una clase.
// La clase Ordenador, será nuestro comparador para ordenar colecciones
public class Ordenardor : IComparer
{
// La enumeración solo será para definir
// si queremos que el orden sea ascendente y descendente
public enum Orden
{
Ascendente,
Descendente
}
private Orden _orden;
private PropertyDescriptor _propiedad;
// El constructor recibe dos parámetro,
// el primero es el nombre de la propiedades que queremos ordenar
// y el segundo el orden; ascendente o descendente,
public Ordenardor(string p_exprOrden, Orden p_orden)
{
// Obtenermos la propuedad de nuestro objeto con la clase TypeDescriptor
_propiedad = TypeDescriptor.GetProperties(typeof(T)).Find(p_exprOrden, false);
this._orden = p_orden;
}
// Implementando el médoto Compare de la interfaz
// Recibe dos parámetros X y Y serán los parámetros a comparar
// Regresa:
// El valor de la condición.
// Si es menor que el valor de X etonces es menor a Y
// Si el valor de X es igual Y.
// Si es mayor a el valor de X entonces es mayor a Y
public int Compare(T p_equis, T p_ye)
{
object equisVal = _propiedad.GetValue(p_equis);
object yeVal = _propiedad.GetValue(p_ye);
// se define en qué dirección debe ordenarse
// -1 Descendente
// 1 Ascendente
int direccion = _orden == Orden.Descendente ? -1 : 1;
if (equisVal is IComparable)
{
IComparable comparableA = equisVal as IComparable;
// Utilizando el método ComparteTo() podemos obtener el valor relativo de
// los objetos que se comparan, utilizando una instancia de cla interfaz IComparable.
// Si es menor a cero entonces la instancia es menor al objeto
// Si es cero entonces son iguales
// Si es mayor a cero la instancia es mayor al objeto
int val = (direccion * comparableA.CompareTo(yeVal));
return val;
}
return 0;
}
}
Después de construir el comprador el siguiente paso es sencillo, definir una lista de objetos y probarlo; primero se definirá una clase para instanciar objetos.
// Esta clase solo define las propiedaes de un objeto,
// el nombre y el tipo, ambas como cadenas
public class Pato
{
private string _nombre;
public string Nombre
{
get { return _nombre; }
set { _nombre = value; }
}
private string _tipo;
public string Tipo
{
get { return _tipo; }
set { _tipo = value; }
}
public Pato(string p_nombre, string p_tipo)
{
this._nombre = p_nombre;
this._tipo = p_tipo;
}
}
Finalmente se probará el ordenamiento en un proyecto de una Aplicación de Consola
class Program
{
static void Main(string[] args)
{
// Creamos una lista de Objetos
List patos = new List();
patos.Add(new Pato("Ducky", "Pato de goma"));
patos.Add(new Pato("Juan", "Pato mexicano"));
patos.Add(new Pato("John", "Pato gringo"));
// AL método Sort() le mandamos como parámetro un objeto Ordenardor,
// con el nombre de la propiedad que queremos ordenar y el tipo de orden
patos.Sort(new Ordenardor("Nombre", Ordenardor.Orden.Ascendente));
ImprimirLista(patos);
// Imprime el siguinte resultado:
//
// Nombre:Ducky, Tipo:Pato de goma
// Nombre:John, Tipo:Pato gringo
// Nombre:Juan, Tipo:Pato mexicano
//
// Ordenados por nombre
Console.WriteLine();
patos.Sort(new Ordenardor("Tipo", Ordenardor.Orden.Ascendente));
ImprimirLista(patos);
// Imprime el siguinte resultado:
//
// Nombre:Ducky, Tipo:Pato de goma
// Nombre:John, Tipo:Pato gringo
// Nombre:Juan, Tipo:Pato mexicano
//
// Ordenados por tipó
Console.ReadLine();
}
// Imprime todos los elementos de la lista
static void ImprimirLista(List p_lista)
{
foreach (Pato pato in p_lista)
{
Console.WriteLine(string.Format("Nombre:{0}, Tipo:{1}", pato.Nombre, pato.Tipo));
}
}
}