自定义泛型集合

自定义泛型集合,完成一些自己想要的操作

 

1.自定义的泛型集合类TravelList.cs,可以根据需要筛选方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
using System.Reflection;
using System.ComponentModel;

namespace CustomList
{
    [Serializable]
    public class TravelList<T> : IEnumerable<T>
    {

        private List<T> innerList;                //内部所使用的List,集合成员保存在这里.

        /// <summary>
        /// 集合描述,用于存储一些附带信息。
        /// 类ChangedPropertyReflector中用到。
        /// </summary>
        public string Description
        {
            get { return _description; }
            set { _description = value; }
        }
        private string _description = "";

        /// <summary>
        /// 集合中元素的临时顺序号属性名,用CodeRobot代码生成器生成的业务实体才有这个属性.
        /// 但是不是用用CodeRobot代码生成器生成的业务实体也可以使用这个集合。
        /// </summary>
        public string SequenceNoPropertyName
        {
            get
            {
                return _sequenceNoPropertyName;
            }
        }
        private string _sequenceNoPropertyName = "TmpSequenceNo";

        public int TmpSequenceNo
        {
            get
            {
                return _tmpSequenceNo;
            }
            protected set
            {
                _tmpSequenceNo = value;
            }
        }
        private int _tmpSequenceNo = 0;

        private string _propertyName;
        private bool _isAscending;         //是否升序排序

        /// <summary>
        /// 排序时使用的一个临时类
        /// </summary>
        private class SortPosition
        {  
            public string propValue;       //某个属性值
            public int start;              //某个属性值开始位置
            public int end;                 //某个属性值结束位置
            public int count;              //某个属性值出现的个数
        }

        private ArrayList sortArray;       //排序时使用的一个临时数组,成员SortPosition

        //构造函数
        public GenericList()
        {
            innerList = new List<T>();
        }

        #region SortBy
        /// <summary>
        /// 把集合成员按照两个属性(字段)的值排序,属性名区分大小写
        /// </summary>
        /// <param name="propertyName">属性名称,区分大小写</param>
        /// <param name="ascending">true表示按升序排序</param>
        public void SortBy(string propertyName, bool ascending)
        {
            if (propertyName == "")
            {
                return;
            }
            if (_propertyName == propertyName && _isAscending == ascending)
                _isAscending = !ascending;
            else
            {
                _propertyName = propertyName;
                _isAscending = ascending;
            }

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            PropertyDescriptor propertyDesc = properties.Find(propertyName, true);

            if (propertyDesc == null)
            {
                throw new Exception("SortBy: Not found property:" + propertyName);
            }

            // 应用排序
            PropertyComparer<T> pc;
            pc = new PropertyComparer<T>(propertyDesc, (_isAscending) ? ListSortDirection.Ascending : ListSortDirection.Descending);
            innerList.Sort(pc);
        }

        /// <summary>
        /// 把集合成员按照两个属性(字段)的值排序,属性名区分大小写
        /// </summary>
        /// <param name="propertyName1"></param>
        /// <param name="propertyName2"></param>
        /// <param name="ascending1">true表示按升序排序</param>
        ///<param name="ascending2">true表示按升序排序</param>
        public void SortBy(string propertyName1, bool ascending1, string propertyName2, bool ascending2)
        {
            if (propertyName1 == "")
            {
                return;
            }

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            PropertyDescriptor propertyDesc = properties.Find(propertyName1, true); 
            if (propertyDesc == null)
            {
                throw new Exception("SortBy: Not found property:" + propertyName1);
            }

            // 应用排序
            PropertyComparer<T> pc;
            pc = new PropertyComparer<T>(propertyDesc, (ascending1) ? ListSortDirection.Ascending : ListSortDirection.Descending);
            innerList.Sort(pc);                       //第一轮按照第一个属性排序

            //开始第二个属性排序的计算
            int index = 0;
            string propVal = "", prevPropVal = "";    //前一个不同的属性值

            SortPosition sp;
            sortArray = new ArrayList();
            foreach (T obj in innerList)
            {
                propVal = (PropertyComparer<T>.GetPropertyValue(obj, propertyName1)).ToString();
                if (index == 0)
                {
                    sp = new SortPosition();
                    sp.propValue = propVal;
                    sp.start = index;
                    sortArray.Add(sp);
                    prevPropVal = propVal;
                }
                else
                {
                    if (propVal != prevPropVal)
                    {
                        //如果有新值出现,则计算前一各值的数量,并将新值所代表的位置加入到sortArray里去.
                        ((SortPosition)sortArray[sortArray.Count - 1]).end = index;
                        ((SortPosition)sortArray[sortArray.Count - 1]).count = index - ((SortPosition)sortArray[sortArray.Count - 1]).start;
                        sp = new SortPosition();
                        sp.propValue = propVal;
                        sp.start = index;
                        sortArray.Add(sp);
                        prevPropVal = propVal;
                    }
                }
                if (index == innerList.Count - 1)
                {   //最后一个

                    ((SortPosition)sortArray[index - 1]).end = index;
                    //最后一个值的数量. sortArray.Count - 2 :sortArray的倒数第二个元素
                    if (propVal != prevPropVal)
                    {
                        ((SortPosition)sortArray[sortArray.Count - 1]).count = index - ((SortPosition)sortArray[sortArray.Count - 2]).end;
                    }
                    else
                    {
                        ((SortPosition)sortArray[sortArray.Count - 1]).count = index - ((SortPosition)sortArray[sortArray.Count - 2]).end + 1;
                    }
                }
                index += 1;
            }

            //第二轮根据第一各属性的每一个不同值,按第二个属性排序

            if (propertyName2 == "")
            {
                return;
            }
            else
            {
                foreach (SortPosition pos in sortArray)
                {
                    propertyDesc = properties.Find(propertyName2, true);
                    pc = new PropertyComparer<T>(propertyDesc, (ascending2) ? ListSortDirection.Ascending : ListSortDirection.Descending);
                    innerList.Sort(pos.start, pos.count, pc);
                }
            }
        }
        #endregion


        #region FindBy
        /// <summary>
        /// 按某个属性(字段)的值在集合中查找对象,找到则返回满足条件的第一个对象,找不到返回对象的默认值。
        /// 属性名是区分大小写的, 对象值转换成字符串比较。
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        /// <param name="IgnoreCase">属性值是否忽略大小写</param>
        /// <returns></returns>
        public T FindBy(string propertyName, object propertyValue, bool ignoreCase)
        {
            T foundObj = default(T);
            string stringValue;
            string tmpVal;
            stringValue = propertyValue.ToString();
            foreach (T obj in innerList)
            {
                tmpVal = PropertyComparer<T>.GetPropertyValue(obj, propertyName).ToString();
                if (String.Compare(tmpVal, stringValue, ignoreCase) == 0)
                {
                    foundObj = obj;
                    break;
                }
            }
            return foundObj;
        }

        /// </summary>
        /// 按两个属性(字段)的值在集合中查找对象,找到则返回满足条件的第一个对象,找不到返回对象的默认值。
        /// 属性名是区分大小写的, 对象值转换成字符串比较。
        /// </summary>
        /// <param name="propertyName1"></param>
        /// <param name="propertyValue1"></param>
        /// <param name="propertyName2"></param>
        /// <param name="propertyValue2"></param>
        /// <param name="ignoreCase">屬性值是否忽略大小写</param>
        /// <returns></returns>
        public T FindBy(string propertyName1, object propertyValue1, string propertyName2, object propertyValue2, bool ignoreCase)
        {
            T foundObj = default(T);
            string stringValue1, stringValue2;
            stringValue1 = propertyValue1.ToString();
            stringValue2 = propertyValue2.ToString();

            foreach (T obj in innerList)
            {
                if (String.Compare(PropertyComparer<T>.GetPropertyValue(obj, propertyName1).ToString(), stringValue1, ignoreCase) == 0 &&
                    String.Compare(PropertyComparer<T>.GetPropertyValue(obj, propertyName2).ToString(), stringValue2, ignoreCase) == 0)
                {
                    foundObj = obj;
                    break;
                }
            }
            return foundObj;
        }

        /// </summary>
        /// 按三个属性(字段)的值在集合中查找对象,找到则返回满足条件的第一个对象,找不到返回对象的默认值。
        /// 属性名是区分大小写的, 对象值转换成字符串比较。
        /// </summary>
        public T FindBy(string propertyName1, object propertyValue1, string propertyName2, object propertyValue2, string propertyName3, object propertyValue3, bool ignoreCase)
        {
            T foundObj = default(T);
            string stringValue1, stringValue2, stringValue3;
            stringValue1 = propertyValue1.ToString();
            stringValue2 = propertyValue2.ToString();
            stringValue3 = propertyValue3.ToString();

            foreach (T obj in innerList)
            {
                if (String.Compare(PropertyComparer<T>.GetPropertyValue(obj, propertyName1).ToString(), stringValue1, ignoreCase) == 0 &&
                    String.Compare(PropertyComparer<T>.GetPropertyValue(obj, propertyName2).ToString(), stringValue2, ignoreCase) == 0 &&
                    String.Compare(PropertyComparer<T>.GetPropertyValue(obj, propertyName3).ToString(), stringValue3, ignoreCase) == 0)
                {
                    foundObj = obj;
                    break;
                }
            }
            return foundObj;
        }
        #endregion

        /// <summary>
        /// 返回某个属性等于某个值的子集合。
        /// 属性名是区分大小写的, 对象值转换成字符串比较。
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        /// <param name="byReference">是否生成一个新的子集合,如果是true, 則子集合里的元素不再是大集合里的元素,而是一个新生成的对象</param>
        /// <param name="ignoreCase">属性值是否忽略大小写</param>
        /// <returns></returns>
        public GenericList<T> GetSubList(string propertyName, object propertyValue, bool ignoreCase)
        {
            GenericList<T> subColletion = new GenericList<T>();
            string stringValue;
            stringValue = propertyValue.ToString();   //轉爲小寫比較
            foreach (T obj in innerList)
            {
                if (String.Compare(PropertyComparer<T>.GetPropertyValue(obj, propertyName).ToString(), stringValue, ignoreCase) == 0)
                {
                    subColletion.Add(obj);
                }
            }
            return subColletion;
        }

        /// <summary> 
        /// 添加元素,并给集合成员的临时顺序号属性赋值. 
        /// </summary>
        public void Add(T obj)
        {
            //对于用代码生成器生成的对象,才有这个属性:_sequenceNoPropertyName
            PropertyInfo pi = obj.GetType().GetProperty(SequenceNoPropertyName);
            if (pi != null)
            {                             //有该属性則赋值再添加,否则直接添加.
                pi.SetValue(obj, TmpSequenceNo, null);
                TmpSequenceNo += 1;
            }
            innerList.Add(obj);
        }

        /// <summary>
        /// 添加元素,并给集合成员的临时顺序号属性赋值. 
        /// </summary>
        public void AddRange(IEnumerable<T> collection)
        {
            foreach (T obj in collection)
            {
                PropertyInfo pi = obj.GetType().GetProperty(SequenceNoPropertyName);
                if (pi != null)
                {
                    pi.SetValue(obj, TmpSequenceNo, null);
                    TmpSequenceNo += 1;
                }
                innerList.Add(obj);
            }
        }

        /// <summary>
        /// 添加元素,并给集合成员的临时顺序号属性赋值. 
        /// </summary>
        public void AddRange(T[] objectArray)
        {
            foreach (T obj in objectArray)
            {
                PropertyInfo pi = obj.GetType().GetProperty(SequenceNoPropertyName);
                if (pi != null)
                {
                    pi.SetValue(obj, TmpSequenceNo, null);
                    TmpSequenceNo += 1;
                }
                innerList.Add(obj);
            }
        }

        public void Insert(int index, T obj)
        {
            PropertyInfo pi = obj.GetType().GetProperty(SequenceNoPropertyName);
            if (pi != null)
            {
                pi.SetValue(obj, TmpSequenceNo, null);
                TmpSequenceNo += 1;
            }
            innerList.Insert(index, obj);
        }

        public void InsertRange(int index, IEnumerable<T> collection)
        {
            int localIndex = index;
            foreach (T obj in collection)
            {
                PropertyInfo pi = obj.GetType().GetProperty(SequenceNoPropertyName);
                if (pi != null)
                {
                    pi.SetValue(obj, TmpSequenceNo, null);
                    TmpSequenceNo += 1;
                }
                innerList.Insert(localIndex, obj);
                localIndex += 1;
            }
        }


        #region 下面实现集合一些常用的属性和方法,一些不常用的方法没有实现,需要时可以自己添加。

        public int Capacity
        {
            get
            {
                return innerList.Capacity;
            }
            set
            {
                innerList.Capacity = value;
            }
        }
        public int Count
        {
            get
            {
                return innerList.Count;
            }
        }

        /// <summary>索引器</summary>
        public T this[int index]
        {
            get
            {
                return ((T)(innerList[index]));
            }
        }

        public void Clear()
        {
            innerList.Clear();
        }
        public bool Contains(T obj)
        {
            return innerList.Contains(obj);
        }
        public int IndexOf(T obj)
        {
            return innerList.IndexOf(obj);
        }
        public int LastIndexOf(T obj)
        {
            return innerList.LastIndexOf(obj);
        }

        public void CopyTo(T[] array)
        {
            innerList.CopyTo(array);
        }
        public void CopyTo(T[] array, int arrayIndex)
        {
            innerList.CopyTo(array, arrayIndex);
        }
        public void CopyTo(int index, T[] array, int arrayIndex, int count)
        {
            innerList.CopyTo(index, array, arrayIndex, count);
        }

        /// <summary>
        /// 拷贝到对象数组
        /// </summary>
        /// <returns></returns>
        public T[] CopyToArray()
        {
            T[] objArray = new T[innerList.Count];
            innerList.CopyTo(objArray);
            return objArray;
        }

        public bool Remove(T obj)
        {
            return innerList.Remove(obj);
        }
        public void RemoveAt(int index)
        {
            innerList.RemoveAt(index);
        }

        /// <summary>List的Find方法</summary>
        public T Find(Predicate<T> match)
        {
            return innerList.Find(match);
        }
        public List<T> FindAll(Predicate<T> match)
        {
            return innerList.FindAll(match);
        }

        public void Sort()
        {
            innerList.Sort();
        }
        public void Sort(IComparer<T> comparer)
        {
            innerList.Sort(comparer);
        }
        #endregion


        #region 实现IEnumerable<T>的成员,绑定GridView所必须

        public IEnumerator<T> GetEnumerator()
        {
            int count = innerList.Count;
            for (int i = 0; i < count; i++)
            {
                yield return innerList[i];
            }
        }

        //实现IEnumerable(非泛型)的成员,因为IEnumerable<T>继承自非泛型IEnumerable.
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        #endregion
    }

}

 2.定义的实体类Travel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CustomListTest
{
    public class Travel
    {
        public Travel(string flight,DateTime flyTime,double price,int seatCount)
        {
            Flight = flight;
            FlyTime = flyTime;
            Price = price;
            SeatCount = seatCount;
        }
        /// <summary>
        /// 航班
        /// </summary>
        public string Flight
        {
            get;
            set;
        }

        /// <summary>
        /// 起飞时间
        /// </summary>
        public DateTime FlyTime
        {
            get;
            set;
        }

        /// <summary>
        /// 价格
        /// </summary>
        public double Price
        {
            get;
            set;
        }

        /// <summary>
        /// 座位剩余量
        /// </summary>
        public int SeatCount
        {
            get;
            set;
        }
    }
}

 3.自定义的一个属性比较的类PropertyComparer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;

namespace CustomListTest
{
    /// <summary>
    /// 属性比较类
    /// </summary>
    public class PropertyComparer<T> : System.Collections.Generic.IComparer<T>
    {

        private PropertyDescriptor _property;
        private ListSortDirection _direction;

        public PropertyComparer(PropertyDescriptor property, ListSortDirection direction)
        {
            _property = property;
            _direction = direction;
        }

        #region IComparer<T>

        public int Compare(T xWord, T yWord)
        {
            // 获取属性
            object xValue = GetPropertyValue(xWord, _property.Name);
            object yValue = GetPropertyValue(yWord, _property.Name);

            // 调用升序或降序方法
            if (_direction == ListSortDirection.Ascending)
            {
                return CompareAscending(xValue, yValue);
            }
            else
            {
                return CompareDescending(xValue, yValue);
            }
        }

        public bool Equals(T xWord, T yWord)
        {
            return xWord.Equals(yWord);
        }

        public int GetHashCode(T obj)
        {
            return obj.GetHashCode();
        }

        #endregion

        /// <summary>
        /// 比较任意类型属性升序
        /// </summary>
        /// <param name="xValue">X值</param>
        /// <param name="yValue">Y值</param>
        /// <returns></returns>
        private int CompareAscending(object xValue, object yValue)
        {
            int result;

            // 如果值实现了IComparer接口
            if (xValue is IComparable)
            {
                result = ((IComparable)xValue).CompareTo(yValue);
            }
            // 如果值没有实现IComparer接口,但是它们是相等的
            else if (xValue.Equals(yValue))
            {
                result = 0;
            }
            // 值没有实现IComparer接口且它们是不相等的, 按照字符串进行比较
            else result = xValue.ToString().CompareTo(yValue.ToString());

            return result;
        }

        /// <summary>
        /// 比较任意类型属性降序
        /// </summary>
        /// <param name="xValue">X值</param>
        /// <param name="yValue">Y值</param>
        /// <returns></returns>
        private int CompareDescending(object xValue, object yValue)
        {
            return CompareAscending(xValue, yValue) * -1;
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="value">对象</param>
        /// <param name="property">属性</param>
        /// <returns></returns>
        public static object GetPropertyValue(T value, string property)
        {
            // 获取属性
            PropertyInfo propertyInfo = value.GetType().GetProperty(property);

            // 返回值
            return propertyInfo.GetValue(value, null);
        }
    }
}

 4.后台调用的简单方法Program.cs,这里只演示了按照属性一的升序和属性二的降序排列

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CustomListTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Travel travel1 = new Travel("1001",DateTime.Now.AddDays(1),151,24);
            Travel travel2 = new Travel("1002", DateTime.Now.AddDays(4), 152, 45);
            Travel travel3 = new Travel("1003", DateTime.Now.AddDays(3), 153, 12);
            Travel travel4 = new Travel("1004", DateTime.Now.AddDays(7), 154, 5);
            Travel travel5 = new Travel("1005", DateTime.Now.AddDays(5), 155, 32);
            Travel travel6= new Travel("1006", DateTime.Now.AddDays(4), 156, 32);
            Travel travel7 = new Travel("1007", DateTime.Now.AddDays(5), 151, 32);
            Travel travel8 = new Travel("1008", DateTime.Now.AddDays(4), 156, 32);
            Travel travel9= new Travel("1009", DateTime.Now.AddDays(7), 151, 32);
            Travel travel10 = new Travel("1010", DateTime.Now.AddDays(7), 152, 32);

            TravelList<Travel> list = new TravelList<Travel>();
            list.Add(travel1);
            list.Add(travel2);
            list.Add(travel3);
            list.Add(travel4);
            list.Add(travel5);
            list.Add(travel6);
            list.Add(travel7);
            list.Add(travel8);
            list.Add(travel9);
            list.Add(travel10);
            list.Sort("FlyTime", true, "Price", false);

            foreach (var item in list)
            {
                Console.WriteLine(item.Flight + " " + item.FlyTime + " " + item.Price + " " + item.SeatCount);
            }
            Console.Read();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值