No more then a few paragraphs of things I want to archive (instead of try to remember)

Friday, October 19, 2007

Using IComparable and IComparer to sort by many child properties

Below is parent Collection code used to allow sorting by many different child properties:


using System.Collections;
using System.Data;
 
namespace CARRS
{
    #region Sort Enumerations
 
    /// <summary>
    /// Lookup Collection Sort Column
    /// </summary>
    public enum LookupCollectionSortColumn
    {
        Id,
        SortNumber,
        Description,
        Code,
        Value
    }
 
    /// <summary>
    /// Lookup Collection Sort Direction
    /// </summary>
    public enum LookupCollectionSortDirection
    {
        Ascending,
        Descending
    }
 
    #endregion
 
    #region Lookup Collection
 
    /// <summary>
    /// Lookup Collection
    /// </summary>
    public class LookupCollection : ReadOnlyCollectionBase
    {
 
        #region Indexer
 
        public Lookup this[int index]
        {
            get { return this[index]; }
        }
 
        #endregion
 
        #region General Object Methods
 
        public int IndexOf(Lookup ob)
        {
            return IndexOf(ob);
        }
 
        public bool Contains(Lookup ob)
        {
            return Contains(ob);
        }
 
        public bool Contains(int id)
        {
            foreach (Lookup ob in this)
            {
                if (ob.Id == id)
                    return true;
            }
 
            return false;
        }
 
        #endregion
 
        #region Sort
 
        public void Sort(LookupCollectionSortColumn sortColumn, LookupCollectionSortDirection sortDirection)
        {
            IComparer ob = new LookupCollectionComparer(sortColumn, sortDirection);
            InnerList.Sort(ob);
        }
 
        public void Sort(LookupCollectionSortColumn sortColumn)
        {
            LookupCollectionComparer ob = new LookupCollectionComparer(sortColumn, LookupCollectionSortDirection.Ascending);
            InnerList.Sort(ob);
        }
 
        public void Sort()
        {
            InnerList.Sort();
        }
 
        #endregion
 
        #region Constructor
 
        public LookupCollection(IDataReader dr)
        {
            while (dr.Read())
            {
                Lookup ob = Lookup.GetLookup(dr);
                InnerList.Add(ob);
            }
        }
 
        #endregion
 
    }
 
    #endregion
 
    #region IComparer Implimentation
 
    /// <summary>
    /// Custom Lookup Collection Sort IComparer implimentation
    /// </summary>
    internal class LookupCollectionComparer : IComparer
    {
 
        private LookupCollectionSortColumn _sortColumn;
        private LookupCollectionSortDirection _sortDirection;
 
        public LookupCollectionComparer(LookupCollectionSortColumn sortColumn, LookupCollectionSortDirection sortirection)
        {
            _sortColumn = sortColumn;
            _sortDirection = sortirection;
        }
 
        public int Compare(object x, object y)
        {
            Lookup Comparer, Comparee;
 
            // define two objects, and sort direction switches their identity, thus switches order
            if (_sortDirection == LookupCollectionSortDirection.Ascending)
            {
                Comparer = (Lookup)x;
                Comparee = (Lookup)y;
            }
            else
            {
                Comparer = (Lookup)y;
                Comparee = (Lookup)x;
            }
 
            // add more columns as defined
            switch (_sortColumn)
            {
                case LookupCollectionSortColumn.SortNumber:
                    return Comparer.SortNumber.CompareTo(Comparee.SortNumber);
                case LookupCollectionSortColumn.Description:
                    return Comparer.Description.CompareTo(Comparee.Description);
                case LookupCollectionSortColumn.Code:
                    return Comparer.Code.CompareTo(Comparee.Code);
                case LookupCollectionSortColumn.Value:
                    return Comparer.Value.CompareTo(Comparee.Value);
                case LookupCollectionSortColumn.Id:
                    return Comparer.Id.CompareTo(Comparee.Id);
                default:
                    return 0;
            }
        }
    }
 
#endregion
 
}


Below is the child object code used by the parent. Notice that we still implement IComparable here as well, to allow for a default .Sort() call:


using System;
using System.Data;
 
namespace CARRS
{
    [Serializable]
    public class Lookup : IComparable<Lookup>
    {
        #region Private Members
 
        private int _id = 0;
        private string _code = string.Empty;
        private string _value = string.Empty;
        private string _description = string.Empty;
        private bool _isActive = true;
        private int _sortNumber = 0;
 
        #endregion
 
        #region Business Properties
 
        public int Id
        {
            get
            {
                return _id;
            }
        }
 
        public string Code
        {
            get
            {
                return _code;
            }
        }
 
        public string Value
        {
            get
            {
                return _value;
            }
        }
 
        public string Description
        {
            get
            {
                return _description;
            }
        }
 
        public bool IsActive
        {
            get
            {
                return _isActive;
            }
        }
 
        public int SortNumber
        {
            get
            {
                return _sortNumber;
            }
        }
 
        #endregion
 
        #region Overrides
 
        public override string ToString()
        {
            return _id.ToString();
        }
 
        public bool Equals(Lookup ob)
        {
            return _id.Equals(ob.Id);
        }
 
        public override int GetHashCode()
        {
            return (_id.ToString()).GetHashCode();
        }
 
        #endregion
 
        #region IComparable Implimentation
 
        public int CompareTo(Lookup ob)
        {
            return _sortNumber.CompareTo(ob.SortNumber);
        }
 
        #endregion
 
        #region Static Members
 
        internal static Lookup GetLookup(IDataReader dr)
        {
            Lookup ob = new Lookup();
            ob.Fetch(dr);
            return ob;
        }
 
        #endregion
 
        #region Constructor
 
        private Lookup()
        {
            // Prevent direct creation
        }
 
        #endregion
 
        #region Data Access
 
        private void Fetch(IDataRecord dr)
        {
            //TODO: if we don't use CSLA.Data.SafeDataReader we will have to validate
            _id = Convert.ToInt32(dr["ID"]);
            _code = dr["Code"].ToString();
            _value = dr["Value"].ToString();
            _description = dr["Description"].ToString();
            _isActive = Convert.ToBoolean(dr["IsActive"]);
            _sortNumber = Convert.ToInt32(dr["SortNumber"]);
        }
 
        #endregion
    }
}



Here is the class diagram for the above: