当想对集合筛选的时候,经常想到用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()的更多相关文章

  1. 关于Linq对DataTable和List各自的两个集合筛选的相关操作技巧

    项目中用到了对两个集合的帅选等操作,简单总结下 1.Linq操作多个Datable 可以通过AsEnumerable()方法对DataTable进行Linq操作 //获取数据表所有数据 DataTab ...

  2. Spring mvc接受集合类型参数的方法

    public String xxxxx(String xxxx, String xxxxx, @RequestParam("parameterList[]") List<St ...

  3. FreeMarker与Spring MVC 4集合的HelloWorld示例

    0.整体的项目结构 1.引入POM <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht ...

  4. CollectionUtils.select 集合筛选

    import org.apache.commons.collections.CollectionUtils;import org.apache.commons.collections.Predicat ...

  5. python3编程技巧二——如何在列表、字典、集合 中根据条件筛选数据

    一.列表筛选数据 # coding=utf-8 from random import randint # 创建随机列表 l = [randint(-10, 10) for i in range(10) ...

  6. 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入

    系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...

  7. C#学习总结之集合

    一.集合接口和类型 命名空间:  集合类型  命名空间  一般集合 System.Collections   泛型集合 System.Collections.Generic   特定类型集合 Syst ...

  8. MVC 使用HandleErrorAttribute统一处理异常

    HandleErrorAttribute继承自FilterAttribute,且实现了IExceptionFilter接口. 属于AOP思想的一种实现,MVC的四大筛选器(权限,动作,结果,异常)中的 ...

  9. asp.net core 2.2 中的过滤器/筛选器(上)

    ASP.NET Core中的过滤器/筛选器 通过使用 ASP.NET Core MVC 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码. 注意:本主题不适用于 Razor 页面. ASP. ...

随机推荐

  1. springMVC源码分析--HttpMessageConverter写write操作(三)

    上一篇博客springMVC源码分析--HttpMessageConverter参数read操作中我们已经简单介绍了参数值转换的read操作,接下来我们介绍一下返回值的处理操作.同样返回值的操作操作也 ...

  2. 每位架构师都应该熟知的 10 个 SOA 设计模式

    这 10 个 SOA 设计模式是如此之重要,其应用是如此之广泛,以至于它们都有些显而易见了. 1. 服务无关 服务无关实现对多种业务通用的逻辑.将服务无关的逻辑分离成离散的服务以方便服务的重用和整合. ...

  3. (转载)solr实现满足指定距离范围条件的搜索

    配置schema.xml <?xml version="1.0" encoding="UTF-8" ?> <schema name=" ...

  4. contabs.js 的使用

    1. 先下载两个文件 https://files.cnblogs.com/files/xiaojf/style.css https://files.cnblogs.com/files/xiaojf/c ...

  5. CentOS7.5搭建ELK6.2.4集群及插件安装

    一 简介 Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎.它允许您快速,近实时地存储,搜索和分析大量数据.它通常用作支持具有复杂搜索功能和需求的应用程序的底层引擎/技术. 下载地址 ...

  6. 002 Jupyter-NoteBook工具介绍(网页版编辑器)

    1.Jupyter-NoteBook位置 在安装完anaconda后,这个工具已经被安装完成. 2.打开 3.功能讲解 目录:C:\Users\dell,这个可以看上面控制台上的信息. 4.其余的功能 ...

  7. Failed to load JavaHL Library. SVN

    以前使用的电脑是32位的,安装的svn可以正常使用,但是现在的电脑室64位的,安装好svn后,把项目提交到svn的过程中,总是弹出来一个错误的对话框: Failed to load JavaHL Li ...

  8. 使用ASP.NET MVC+Entity Framework快速搭建系统

    详细资料: http://www.cnblogs.com/dingfangbo/p/5771741.html 学习 ASP.NET MVC 也有一段时间了,打算弄个小程序练练手,做为学习过程中的记录和 ...

  9. QQ怎么 发送 已经录好的视频

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha QQ发送 已经录好的视频 直接放过去,对方是需要下载的. 只有通过QQ录制的,才是直接就 ...

  10. luoguP3185 [HNOI2007]分裂游戏 枚举 + 博弈论

    每个位置的瓶子中的每个石子是一个独立的游戏 只要计算出他们的\(sg\)值即可 至于方案数,反正不多\(n^3\)暴力枚举即可 反正怎么暴力都能过啊 复杂度\(O(Tn^3)\) #include & ...