对象的排序

对象的排序

 

对象的排序和对象的筛选一样很重要,在对业务对象进行排序时,不能使用ObjectDataSource作为数据源,因为它只支持对DataView,DataTableDataSet的自动排序.但是仍然可以对GridView编写Sorting事件的处理方法,通过拼装SQL语句,使用”Order by”子句来完成排序.

 

和进行筛选的思路一样,如果我们将业务对象缓存在服务器上,第一次访问时从数据库提取数据,然后进行缓存,后继的请求只针对缓存了的业务对象进行,这样可以降低对数据库的依赖,提高效率.

 

简单排序

            List<int> list = new List<int>();
            list.Add(4);
            list.Add(5);
            list.Add(2);
            list.Add(9);
            list.Add(1);
 
            list.Sort();//队列表进行排序


可以看到,我们可以通过在List<int>上使用Sort()方法,对列表中的元素进行排序.现在我们在OrderManager.cs中心添一个方法GetSortList(),改革方法用于获取列表对象,因为GetList()方法返回的记录数太多,而在本节我们仅关注排序,所以仅返回15条记录.

        public static List<Order> GetSortList()
        {
            List<Order> list = HttpContext.Current.Cache["sortList"] as list<Order>;
            if (list == null)
            {
                list = GetList("select top 15 OrderId,CustomerId,ShipCountry,OrderDate From Orders");
                HttpContext.Current.Cache.Insert("sortList",list);                
            }
            return list;
        }


 

关于简单排序的东西我不想多说了,因为你总能找到办法来解决,下来咱们来说一下高级排序.

 

多个属性组合排序

 

1.IComparer<T>接口介绍

上面仅仅是为了列表提供了一个默认排序,实际上,我们经常要求对多个列进行排序,还会要求按照升序或是降序,我们甚至会要求对多个列的组合进行排序,比如,先对CustomerId进行升序排序,再对OrderData降序排序.此时虽然使用CompareTo(Order other)也能实现,但是要给Order对象添加额外的字段或者属性.这些.NET框架已经考虑过了,并提供了IComparer<T>接口封装了排序规则,我们可以通过实现这个接口来完成排序.

public interface IComparer<T>
{
int Compare(T x,T y);
}

IComparer<T>只需要实现一个方法,Compare()接受两个同一类型的参数,并返回int类型的结果,IComparable<T>类似,当返回值小于0,表示x<y;等于0,表示x=y;大于0,表示x>y.需要注意的是:这个接口不是要求Order对象实现它,而是要求另一个对象实现它,比如OrderComparer,而在调用Sort()方法时,将它作为参数传递进去.因为这个OrderComparer只是用于对Order对象进行排序,不能应用于其他对象,所以我们将它声明为Order的嵌套类.

 
2.实现IComparer<T>接口

打开Order.cs文件,对它进行如下修改,先添加一个枚举SortDirection,用于表示排序的方向:

        //可复用的枚举,表示排序的方向
        public enum SortDirection
        {
            Ascending=0,
            Descending
        }

Order类的内部,添加一个枚举,这个枚举类型代表了可以进行排序的属性:

        //嵌套枚举,仅应用于此业务对象,可排序的属性
        public enum SortField
        {
            OrderId,
            CustomerId,
            OrderDate,
            Country
        }


我们还需要再定义一个结构Sorter,这个结构包含两个字段,一个SortDirection类型,一个SortField类型,它封装了排序的必要信息:哪个属性按照哪种方式(升序还是降序)排序.

由于这个结构依然只是针对Order对象的,所以我们还是把它定义在Order内部:

        //嵌套结构,仅应用于此业务对象,排序的属性和方法
        public struct Sorter
        {
            public SortField field;
            public SortDirection direction;
            public Sorter(SortField field,SortDirection direction)
            {
                this.field = field;
                this.direction = direction;
            }
            public Sorter(SortField field)
            {
                this.field = field;
                this.direction = SortDirection.Ascending;
            }
        }


接着,我们在Order内部定义实现IComparer<T>的类OrderComparer:

//嵌套类,仅对此业务对象进行排序
        public class OrderComparer : IComparer<Order>
        { }

问题的关键是如何实现这个类:因为我们要实现对某个属性按照某种方式进行排序,那么我们至少要将这两个参数传递进去,所以OrderComparer应该包含用于排序的SortDireactionSortField;因为我们期望可以对多个属性组合排序,所以应该维护一个他们的列表,SortDirectionSortField已经包含在Sorter结构中了,因此只要维护一个List<Sorter>结构就可以了:

        public class OrderComparer : IComparer<Order>
        {
            private List<Sorter> list;
 
            //构造函数,设定排序字段列表
            public OrderComparer(List<Sorter> list)
            {
                this.list = list;
            }
        }

接着考虑如何排序,先从简单入手,我们不考虑对于多个属性的排序,只对某个属性按某种方式排序,那么我们需要添加一个CompareTo()方法,他接受排序的属性,排序的方式以及排序的两个对象,最后返回int类型,用于说明这两个对象的大小(位置的先后):

public int Compare(Order x,Order y,SortField field,SortDirection direction)
            {
                int result = 0;//默认排序位置不变化
                switch (field)
                {
                    case SortField.OrderId:
                        if (direction==SortDirection.Ascending)
                        {
                            result = x.OrderId.CompareTo(y.OrderId);
                        }
                        else
                        {
                            result = y.OrderId.CompareTo(x.OrderId);
                        }
                        break;
                    case SortField.CustomerId:
                        if (direction==SortDirection.Ascending)
                        {
                            result = x.CustomerId.CompareTo(y.CustomerId);
                        }
                        else
                        {
                            result = y.CustomerId.CompareTo(x.CustomerId);
                        }
                        break;
                    case SortField.OrderDate:
                        if (direction==SortDirection.Ascending)
                        {
                            result = x.OrderDate.CompareTo(y.OrderDate);
                        }
                        else
                        {
                            result = y.OrderDate.CompareTo(y.OrderDate);
                        }
                        break;
                    case SortField.Country:
                        if (direction==SortDirection.Ascending)
                        {
                            result = x.Country.CompareTo(y.Country);
                        }
                        else
                        {
                            result = y.Country.CompareTo(x.Country);
                        }
                        break;
                    default:
                        break;
                }
                return result;
            }


但是这个方法不会去实现IComparer<T>接口,也没有办法进行多个列的排序.在进一步深入之前,我们考虑一下如何对两个对象的多个属性(比如A,B,C)来进行排序:先对属性A进行比较,如果属性A相同,则继续比较属性B;如果属性B相同,则继续比较属性C.在这个过程中,只要有任意一个属性不相同,就可以决定两个对象的先后顺序,也就是不再进行后面属性的比较.

 

所以,我们现在实现IComparer<T>接口,编写方法如下:

            public int Compare(Order x, Order y)
            {
                int result = 0;
                foreach (Sorter item in list)
                {
                    result = Compare(x,y,item.field,item.direction);
                    if (result!=0)
                    {
                        break;
                    }
                }
                return result;
            }


在这个方法中,我们遍历了List<Sorter>,并且在foreach语句中调用了我们前面定义的对单个属性的比较方法:

public int Compare(Order x,Order y,SortField field,SortDirection direction)

一旦比较结果不为0,那么就跳出循环.

 

好了,OrderComparer类的实现已经完成了,我们再看一下还有哪些地方可以完善:如果以后每次调用Sort进行排序的时候,都要先创建列表,指定排序规则,构造OrderCompare对象,显然会很麻烦,所以我们可以在类中添加一组重载了的方法GetCompare()用来简化以后调用时的操作步骤(当然这属于锦上添花的事情):

 

            //指定排序属性和排序方式
            public static OrderComparer GetComparer(SortField field, SortDirection direction)
            {
                List<Sorter> list = new List<Sorter>();
                Sorter sorter = new Sorter();
                list.Add(sorter);
                return new OrderComparer(list);
            }
 
            //排序列表
            public static OrderComparer GetComparer(List<Sorter>list)
            {
                return new OrderComparer(list);
            }

好了,这样的话,现在OrderComparer类就全部创建好了,接下来就是看看咋使用.

如何使用?楼主是没搞明白,如果有高手明白,或者你有想法们欢迎留言.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值