Ordenar colecciones de objetos en base a sus propiedades

by jesusoviedo 13. agosto 2009 07:26

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));
            }
        }
    }

Tags: , ,

dotNet

Agregar Comentario


(Su Gravatar icono será mostrado)

  Country flag

biuquote
  • Comentario
  • Vista Previa
Loading



Disclaimer
Las opiniones mostradas en este blog son responsabilidad del autor y sólo son con la finalidad de compartir conocimientos a la comunidad de tecnologías de información.

© Copyright 2010 Mindev