MVC对集合筛选,不使用Where(),而使用FindAll()
当想对集合筛选的时候,经常想到用Where过滤,而实际上List<T>.FindAll()也是不错的选择。
如果有一个订单,属性有下单时间、区域等等。如何使用List<T>.FindAll(),根据年份、月份、天、区域来过滤呢?
□ 思路
List<T>.FindAll(Predicate<T> match)方法
Predicate<T>是一个泛型委托,返回bool类型:
public delegate bool Predicate<T>(T obj)
也就是说,match参数是一个返回bool类型的方法,由此,我们可以定义一个泛型类,并在其中自定义返回bool类型的方法,即筛选规则,最后把该方法交给委托。
最终视图界面输入年份、月份、天与订单类中的下单时间属性进行比较。首先想到把年份、月份、天封装到一个类中与订单类进行比较。考虑到有可能存在其它类也有时间属性,都有可能进行有关时间的筛选。这样,可以把时间属性抽象成接口,凡是实现该接口的,都可以与封装年份、月份、天的类进行比较。
using System;
namespace ObjectFilter.Interface
{
public interface IDate
{
DateTime Date { get; set; }
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
让Order类实现IDate接口。
using System;
using ObjectFilter.Interface;
namespace ObjectFilter.Models
{
public class Order : IDate
{
public int ID { get; set; }
public DateTime Date { get; set; } //接口属性
public string Area { get; set; }
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
封装年份、月份、天的类需要面向IDate接口,并提供一个返回bool类型的比较方法。
public class DateFilter<T> where T:IDate
{
private int year;
private int month;
private int day;
public DateFilter(int year, int month, int day)
{
this.year = year;
this.month = month;
this.day = day;
}
public DateFilter(DateTime date) : this(date.Year, date.Month, date.Day){}
public DateFilter(int year, int month) : this(year, month, 0){}
public DateFilter(int year) : this(year, 0, 0){}
public DateFilter() : this(0, 0, 0){}
//自定义规则:只要有T的Date属性值与本类的字段有一个不等,就返回false
public virtual bool MatchRule(T item)
{
if(year != 0 && year !=item.Date.Year)
return false;
if(month != 0 && month != item.Date.Month)
return false;
if(day !=0 && day != item.Date.Day)
return false;
return true;
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
如何针对Order中的Area属性筛选呢?可以设计一个DateFilter<Order>的继承类,使子类不但有父类的筛选逻辑,并在此基础上增加一个对Area属性的筛选。
1: public class OrderFilter : DateFilter<Order>
2: {
3: private string area;
4:
5: public OrderFilter(int year, int month, int day, string area)
6: : base(year, month, day)
7: {
8: this.area = area;
9: }
10:
11: public override bool MatchRule(Order item)
12: {
13: bool result = base.MatchRule(item);
14: if (result == false)
15: return false;
16: if (string.IsNullOrEmpty(area) || String.Compare(item.Area, area, true) == 0)
17: {
18: return true;
19: }
20: else
21: {
22: return false;
23: }
24: }
25: }
26:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
模拟一个服务层,一个方法用来获取所有订单信息,另一个方法根据条件筛选出订单集合,只需要把自定义泛型类DateFilter<Order>的MatchRule交给Predicate<T>泛型委托就行。
using System;
using System.Collections.Generic;
using ObjectFilter.Helper;
using ObjectFilter.Models;
namespace ObjectFilter
{
public static class Service
{
public static List<Order> GetOrders()
{
return new List<Order>()
{
new Order(){ID = 1,Area = "青岛",Date = new DateTime(2013,8,1)},
new Order(){ID = 2,Area = "平度",Date = new DateTime(2013,9,1)},
new Order(){ID = 3,Area = "即墨",Date = new DateTime(2013,9,3)},
new Order(){ID = 4,Area = "香港",Date = new DateTime(2013,9,3)},
new Order(){ID = 5,Area = "北京",Date = new DateTime(2014,1,2)},
new Order(){ID = 6,Area = "上海",Date = new DateTime(2014,1,2)},
};
}
public static List<Order> GetOrdersBy(DateFilter<Order> filter)
{
return GetOrders().FindAll(new Predicate<Order>(filter.MatchRule));
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
控制器有2个方法,一个方法返回所有的订单,另一个方法接收来自前台的筛选参数,根据这些参数生成自定义泛型类DateFilter<Order>实例作为服务层方法参数,最终返回部分视图。
using ObjectFilter.Helper;
using ObjectFilter.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ObjectFilter.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
List<SelectListItem> years = new List<SelectListItem>();
years.Add(new SelectListItem(){Text = "2013",Value = "2013"});
years.Add(new SelectListItem() { Text = "2014", Value = "2014" });
ViewData["y"] = years;
List<SelectListItem> months = new List<SelectListItem>();
for (int i = 1; i <= 12; i++)
{
months.Add(new SelectListItem(){Text =i.ToString(),Value = i.ToString()});
}
ViewData["m"] = months;
List<SelectListItem> days = new List<SelectListItem>();
for (int i = 1; i <= 31; i++)
{
days.Add(new SelectListItem(){Text = i.ToString(),Value = i.ToString()});
}
ViewData["d"] = days;
return View(Service.GetOrders());
}
[HttpPost]
public ActionResult GetOrdersBy(string y, string m, string d, string area)
{
DateFilter<Order> filter = new OrderFilter(Convert.ToInt32(y), Convert.ToInt32(m), Convert.ToInt32(d), area);
return View(Service.GetOrdersBy(filter));
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
呈现所有订单的视图界面中,当点击"筛选"按钮,把筛选条件通过ajax传递给控制器方法,返回的部分视图最终呈现到本页的一个div中。
展开@model IEnumerable<ObjectFilter.Models.Order>
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@Html.DropDownList("year",(IEnumerable<SelectListItem>)ViewData["y"],"选择年份",new {id="year"}) <br/>
@Html.DropDownList("month",(IEnumerable<SelectListItem>)ViewData["m"],"选择月份",new {id="month"}) <br/>
@Html.DropDownList("day",(IEnumerable<SelectListItem>)ViewData["d"],"选择天数",new {id="day"}) <br/>
<input type="text" id="area"/> <br/>
<input type="button" id="btn" value="筛选"/>
<div id="content">
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.Date)
</th>
<th>
@Html.DisplayNameFor(model => model.Area)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Date)
</td>
<td>
@Html.DisplayFor(modelItem => item.Area)
</td>
<td>
</td>
</tr>
}
</table>
</div>
<hr/>
<h3>以下为筛选结果:</h3>
<div id="filter"></div>
@section scripts
{
<script type="text/javascript">
$(function() {
$('#btn').on('click', function() {
$.ajax({
cache: false,
url: '@Url.Action("GetOrdersBy", "Home")',
type: "POST",
data: { y: $('#year').val(), m: $('#month').val(), d: $('#day').val(), area: $('#area').val() },
success: function (data) {
$('#filter').html(data);
},
error: function (jqXhr, textStatus, errorThrown) {
alert("出错了 '" + jqXhr.status + "' (状态: '" + textStatus + "', 错误为: '" + errorThrown + "')");
}
});
});
});
</script>
}
点击"筛选"按钮返回部分视图为:
@model IEnumerable<ObjectFilter.Models.Order>
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.Date)
</th>
<th>
@Html.DisplayNameFor(model => model.Area)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Date)
</td>
<td>
@Html.DisplayFor(modelItem => item.Area)
</td>
<td>
</td>
</tr>
}
</table>
结果:
输入时间筛选:

输入时间和区域筛选:

□ 总结
先把目标对象中需要筛选的属性抽象成接口属性,然后设计一个能接收筛选条件的泛型类,并提供一个返回bool类型的方法,该方法把接收到的来自客户端的筛选条件与目标对象的属性进行比较。最后,只需要把自定义泛型类返回bool类型的方法交给Predicate<T>这个泛型委托即可:FindAll(new Predicate<Order>(filter.MatchRule))。
MVC对集合筛选,不使用Where(),而使用FindAll()的更多相关文章
- 关于Linq对DataTable和List各自的两个集合筛选的相关操作技巧
项目中用到了对两个集合的帅选等操作,简单总结下 1.Linq操作多个Datable 可以通过AsEnumerable()方法对DataTable进行Linq操作 //获取数据表所有数据 DataTab ...
- Spring mvc接受集合类型参数的方法
public String xxxxx(String xxxx, String xxxxx, @RequestParam("parameterList[]") List<St ...
- FreeMarker与Spring MVC 4集合的HelloWorld示例
0.整体的项目结构 1.引入POM <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht ...
- CollectionUtils.select 集合筛选
import org.apache.commons.collections.CollectionUtils;import org.apache.commons.collections.Predicat ...
- python3编程技巧二——如何在列表、字典、集合 中根据条件筛选数据
一.列表筛选数据 # coding=utf-8 from random import randint # 创建随机列表 l = [randint(-10, 10) for i in range(10) ...
- 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入
系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...
- C#学习总结之集合
一.集合接口和类型 命名空间: 集合类型 命名空间 一般集合 System.Collections 泛型集合 System.Collections.Generic 特定类型集合 Syst ...
- MVC 使用HandleErrorAttribute统一处理异常
HandleErrorAttribute继承自FilterAttribute,且实现了IExceptionFilter接口. 属于AOP思想的一种实现,MVC的四大筛选器(权限,动作,结果,异常)中的 ...
- asp.net core 2.2 中的过滤器/筛选器(上)
ASP.NET Core中的过滤器/筛选器 通过使用 ASP.NET Core MVC 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码. 注意:本主题不适用于 Razor 页面. ASP. ...
随机推荐
- 2018JAVA复习摘要
由于公司内部原因,2018年感觉自己可能会换个新环境:虽然时间尚未确定,但还是得提前做好防范,毕竟面试复习是需要时间好好准备才能拿到自己理想的offer.打算从清明节之后开始好复习基本知识要点,先整理 ...
- SQLSERVER中的非工作时间不得插入数据的触发器的实现
create trigger trigger_nameon table_namefor insert,update,deleteasif (datepart(yy,getdate())%4=0 or ...
- CF 577A 分解因数
输入一个n 构成一个n*n的表 这个表里的数 第i行j列的值为i*j 问x在这个表里出现了几次 Sample test(s)input10 5output2input6 12output4input5 ...
- Web前端开发最佳实践系列文章汇总
Web前端开发最佳实践(1):前端开发概述 Web前端开发最佳实践(2):前端代码重构 Web前端开发最佳实践(3):前端代码和资源的压缩与合并 Web前端开发最佳实践(4):在页面中添加必要的met ...
- USACO 5.4 Character Recognition
Character Recognition This problem requires you to write a program that performs character recogniti ...
- html中<b>标签和<Strong>标签的区别
关于html标签中b和strong两个的区别,我也是今早上才注意的,以前都是混着用的,早上看书的时候才注意到这两个标签的区别. 用在网页上,默认情况下它们起的均是加粗字体的作用,二者所不同的是,< ...
- bzoj 1295 1295: [SCOI2009]最长距离
思路:对于每个点出发bfs做一次dp, dp[ i ][ j ][ k ] 表示从枚举的该点能不能经过k个障碍物到达(i , j). #include<bits/stdc++.h> #de ...
- hdoj2191 珍惜现在,感恩生活(01背包 || 多重背包)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2191 思路 由于每种大米可能不止一袋,所以是多重背包问题,可以直接使用解决多重背包问题的方法,也可以将 ...
- 如何使用django显示一张图片
django显示图片对新手来说真的算是一个坑.. 这里记录下小白爬坑的历程. 首先,你需要一个可以运行的django服务器,能显示正常的html文本,无法显示图片 这是html的文本,可以显示文字,无 ...
- 【基础知识】ASP.NET[基础二(aspx)]
1.cs可以调用aspx中的runat=server控件,aspx中也可以访问测试中定义的字段.函数,还可以编写复杂的C#代码,for等所有C#代码都可以写在aspx中(不推荐这样写): 2.把代码写 ...