通常呢我们需要翻页的数据大多都是从数据库中取,翻页、筛选、排序啥的都是通过SQL语句由数据库帮我搞定,那么有些需求没有数据库呢?或者有些数据只存在于内存中不存到数据库呢?怎么实现内存里面的对象集合的通用翻页呢?好吧,好在.net framework 3.5 新增加的LINQ to Object里面提供非常多的扩展方法,让我们省去了很多Object集合的操作,如是乎就在想,能不能做一个像数据库一样的,能做一个通用的满足翻页、筛选、排序的方法呢?
为了防止有些网站乱爬这里插个声明,本文章版权归作者及博客园所有!链接:http://www.cnblogs.com/fanqie-liuxiao
一、准备
继续阅读需要必须了解的小知识点(大鸟跳过):
扩展方法:
简单的个人理解,就是允许在一些无法继承的、Final类一的些扩展。是不是有点儿像很早以前javascript里面的扩展那些个浏览器对象来的?(到最后搞的乱七八遭/偷笑)。
来个例子吧。
public static class extendClass
{
// 比如,我要给List这个泛型集合添加一个MyPrint方法。我们可以这样做,注意函数签名.
public static String MyPrint(this IEnumerable
调用:
List list = new List();
list.Add(new gameProduct(1, 101, 100));
list.Add(new gameProduct(1, 102, 2));
list.MyPrint();
lambda表达式:
简单的个人理解,一个方便函数回调的一种写法,省去繁琐的委托定义,实际就是其实是个(委托+匿名函数)的简化写法,为什么我们要这么写?因为写程序里面有一个很重要的概念就是Callback,实现低耦合。有没有经验用javascript做轮子的朋友一定是痛彻心扉,哈哈。
来个例子吧。
List list = new List();
list.Add(new gameProduct(1, 101, 100));
list.Add(new gameProduct(1, 102, 2));
list.Add(new gameProduct(1, 101, 50));
list.Add(new gameProduct(2, 106, 13));
list.Add(new gameProduct(2, 103, 18));
list.Add(new gameProduct(5, 118, 9));
var enum_1 = list.Select(g => g);
// var enum_2 = list.Select(delegate(gameProduct g){return g;});// 这个就是g => g
Console.WriteLine(enum_1.MyPrint()); // 看它返回的是什么,先来体验一下
好吧,鄙人新手。准备知识就先讲这么多,以上的个人理解如果说的不恰当之处还请谅解或者留言讨论,如果对您有一丝丝的帮助,烦请您点个赞。如果您觉得这非常之烂,请把赞当“踩”点一下,好歹请我知道哈。
二 、实现通用集合对象翻页
上面废话扯太多了,这里就直接上代码啦
///
/// 内存对象翻页
///
/// 实体类型
/// 当前页数
/// 每页的条数
/// 实体集合
/// 筛选实体参数
/// 主键
/// 排序字段
/// 翻页数据
public static object Pager(int pageIndex, int pageSize, List source, Ttable filterModel, String pk = "ID", String order = "ID")
where Ttable : EntityObject
{
try
{
Func filterItem = null; // 筛选回调函数指针
Func orderItem = null; // 排序回调函数指针
#region 处理筛选条件
if (filterModel != null)
{
foreach (var item in filterModel.GetType().GetProperties()) // 遍历筛选条件
{
object pro = item.GetValue(filterModel, null);
string proName = item.Name;
if (pro != null)
{
if (pro.GetType() == typeof(int) && !proName.Equals(pk)) // 当过滤参数类型为int类型的时候,屏蔽主键
{
filterItem += new Func(
delegate(Ttable model)
{
object modelPro = item.GetValue(model, null);
if (modelPro == pro)
{
return true;
}
return false;
});
}
if (pro.GetType() == typeof(string) && !pro.ToString().Equals("")) // 当过滤参数为String类型的时候,屏蔽空字符串
{
filterItem += new Func(
delegate(Ttable model)
{
String modelPro = item.GetValue(model, null).ToString();
if (modelPro.IndexOf(pro.ToString()) >= 0)
{
return true;
}
return false;
});
}
// ...
}
if (proName.Equals(order)) // 排序判断回调
{
if (pro.GetType() == typeof(int)) // 只对Int类型数据进行排序判断
{
orderItem += new Func(
delegate(Ttable model)
{
int modelPro = (int)item.GetValue(model, null);
return modelPro;
});
}
}
}
}
var vList = source.Where(m =>
{
Boolean mrt = false;
if (filterItem != null)
{
if (filterItem(m)) // 筛选数据判断,每一条数据都会判断一下,所以回调函数存在效率问题
{
mrt = true;
}
}
else
{
mrt = true;
}
return mrt;
}); // 筛选后数据集
#endregion
#region 求总数
Int32 totalCount = vList.Count(); // 当前筛选条件的总条数
if (totalCount <= (pageIndex - 1) * pageSize) // 当前页数没有记录
{
return new Models.PageModel() { TotalCount = 0, Data = new List() };
}
#endregion
#region 处理排序
if (orderItem != null)
{
vList = vList.OrderBy(orderItem, new CompareIntegers());
}
#endregion
#region 处理翻页
vList = vList.Skip((pageIndex - 1) * pageSize).Take(pageSize);
Models.PageModel pm = new Models.PageModel() { TotalCount = totalCount, Data = vList.ToList() };
return pm;
#endregion
}
catch { }
return null;
}
// DESC
public class CompareIntegers : IComparer
{
public int Compare(int i1, int i2)
{
return i2 - i1;
}
}
声明一下哈,这样的写法是一定存在性能问题的,我们这里只讲功能实现哈,这里以学习为主。有啥好的建议或者意见呢,大可留言扇我。
调用实例:
public JsonResult Pager_Json2(FormCollection fm)
{
object oRT = null;
try
{
Int32 pageIndex = Int32.Parse(fm["page"]);
Int32 pageSize = Int32.Parse(fm["rows"]);
TB_Devices tb_model = JsonConvert.DeserializeObject(fm["ParamString"]);
List listObject = TaskManager.Service.TaskService.Instance.GetDevice(-1);
oRT = Helper.PagerHelper.Pager(pageIndex, pageSize, listObject, tb_model, "D_ID", "D_ID");
}
catch { }
return Json(oRT, JsonRequestBehavior.AllowGet);
}
好吧,写的有点儿累了,可能对实用价值并不大,看在我写了这么多代码的份子上,敬请的“赞”当“踩”。