模仿DotnetCore中间件的方式,做一个列表过滤的功能
我们的很多功能当中都会遇到对版本进行过滤的场合,例如你可能需要对列表中的数据的时间进行过滤、版本过滤、渠道以及地区信息进行过滤。
原本的做法:设计很多个过滤方法,通过枚举的方式组合,选择需要过滤哪些方法,然后一个方法一个方法的调用。 这样的做法本身没什么问题。但是感觉很面向过程,不够面向对象。
通过学习.Net Core的源码,我们可以了解到它采用了一种委托链表的方式,将所有的中间件都串了起来。所以我想要仿造它这个去实现一下这个功能。
这样做的好处:抽象出一些过滤的方法,对于不同的系统,只要通过Use方法,就可以增加我们的过滤规则,考虑到不同的系统过滤的规则不同,这样做也比较灵活(例如 应用管理系统 需要过滤版本、渠道、地区 ,而黑白名单需要过滤版本、渠道、时间等等,那么对于前者我只需要在过滤的时候 UseVersion UserChannel UseArea, 对于后者把UserArea缓存UseTime即可。)
废话不多说:上码
1.定义一个委托类型,承载我们过滤方法
namespace FilterDelegate
{
public delegate IEnumerable<TcySysApplication> TcySysFilterDelegate(IEnumerable<TcySysApplication> applist, TcySysFilterConditionInfo conditionInfo );
}
委托的输入是我们待处理的数据列表appList, 以及我们执行过滤的条件数据。
2.定义一个Builder类,主要用于构建我们整个过滤器,里面主要有两个方法Use方法以及Build方法,Use方法主要用于往我们的委托列表里面增加过滤委托,Build方法主要用于生成最后的过滤器
private readonly IList<Func<TcySysFilterDelegate, TcySysFilterDelegate>> _components = new List<Func<TcySysFilterDelegate, TcySysFilterDelegate>>(); public TcySysFilterBuilder()
{ } public TcySysFilterBuilder Use(Func<TcySysFilterDelegate, TcySysFilterDelegate> filterItem)
{
_components.Add(filterItem);
return this;
} public TcySysFilterDelegate Build()
{
TcySysFilterDelegate last = (applist,filterInfo) =>
{
Console.WriteLine("过滤完成");
return applist;
}; foreach (var component in _components.Reverse())
{
last = component(last);
} return last;
}
3.定义一堆过滤方法,这里没有写具体的逻辑,每一个方法都是通过Builder.Use将委托加入到委托链中
public static TcySysFilterBuilder UseTimeFilter(this TcySysFilterBuilder builder)
{
return builder.Use(next =>
{
return (list, filterInfo) =>
{
Console.WriteLine("我是时间过滤");
return next(list, filterInfo);
};
});
} public static TcySysFilterBuilder UseChannelFilter(this TcySysFilterBuilder builder)
{
return builder.Use(next =>
{
return (list, filterInfo) =>
{
Console.WriteLine("我是渠道过滤"); list = list.Where(x => x.ChannelId != filterInfo.ChannelId); return next(list, filterInfo);
};
});
} public static TcySysFilterBuilder UseVersionFilter(this TcySysFilterBuilder builder)
{
return builder.Use(next =>
{
return (list, filterInfo) =>
{
Console.WriteLine("我是版本过滤");
return next(list, filterInfo);
};
});
}
4.其他类型
public class TcySysApplication
{
public long AppId { set; get; }
public string Name { set; get; }
public long ChannelId { set; get; }
public long Version { set; get; }
public string Province { set; get; }
public string City { set; get; }
public string District { set; get; }
} public class TcySysFilterConditionInfo
{
public long ChannelId { set; get; }
public long Version { set; get; }
public string Province { set; get; }
public string City { set; get; }
public string District { set; get; }
}
5.执行使用
class Program
{
static void Main(string[] args)
{
var sourceList = new List<TcySysApplication>(); sourceList.Add(new TcySysApplication {
AppId =1000,
ChannelId = 88215,
District = "",
City = "乌鲁木齐",
Province = "新疆",
Name ="爱玩不玩",
Version = 10001
}); sourceList.Add(new TcySysApplication
{
AppId = 1001,
ChannelId = 310200,
District = "",
City = "乌鲁木齐",
Province = "新疆",
Name = "爱玩不玩2",
Version = 10002
}); var filterInfo = new TcySysFilterConditionInfo
{
ChannelId = 310200,
District = "",
City = "北京",
Province = "北京",
Version = 10002
}; var builder = new TcySysFilterBuilder(); builder.UseTimeFilter()
.UseChannelFilter()
.UseVersionFilter(); var filter = builder.Build(); var result = filter(sourceList, filterInfo); foreach (var item in result)
{
Console.WriteLine($"AppId={item.AppId} AppName={item.Name} ChannelId={item.ChannelId}");
} Console.ReadKey();
}
}
图上我使用了三种过滤,其中因为Channel中有过滤的逻辑,根据这个逻辑我们应该只会返回一个Channeld = 88215的数据
我们可以将 UseChannelFilter 那句代码注释掉,再运行,由于没有过滤渠道,此时显示了两条数据
模仿DotnetCore中间件的方式,做一个列表过滤的功能的更多相关文章
- 用小程序做一个类似于苹果AssistiveTouch功能
一.首先我先介绍一下,我们要做一个什么样的项目功能 项目功能就是一个音频点击播放,当点击为播放的状态时,一个音频的动图出现,而且是可以跟随着手指的滑动而滑动,而且,在滑动动图的时候,当前下的页面是不可 ...
- SpringBoot2.x整合Email并利用AOP做一个项目异常通知功能
因为不知aop能干嘛,因此用aop做个小功能,再结合最近学的springboot-Email做了个系统异常自动邮件通知的功能, 感觉满满的成就感. AOP不懂的可以看上一篇:https://www.c ...
- QT 创建一个具有复选功能的下拉列表控件
最近研究了好多东西,前两天突然想做一个具有复选功能的下拉列表框.然后在网上"学习"了很久之后,终于发现了一个可以用的,特地发出来记录一下. 一.第一步肯定是先创建一个PROJECT ...
- [转]jsPlumb插件做一个模仿viso的可拖拉流程图
原贴:https://www.cnblogs.com/sggx/p/3836432.html 前言 这是我第一次写博客,心情还是有点小小的激动!这次主要分享的是用jsPlumb,做一个可以给用户自定义 ...
- react实例之todo,做一个实时响应的列表操作
react实例之todo, 做一个实时响应的列表操作 在所有的mvc框架中,最常见的例子不是hello world,而是todo,由于reactjs的简单性,在不引用flux和redux的情况下,我们 ...
- jsPlumb插件做一个模仿viso的可拖拉流程图
前言 这是我第一次写博客,心情还是有点小小的激动!这次主要分享的是用jsPlumb,做一个可以给用户自定义拖拉的流程图,并且可以序列化保存在服务器端. 我在这次的实现上面做得比较粗糙,还有分享我在做j ...
- 启动django应用报错 “Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。”
启动django应用时报如下错误 "Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试." 网上查了一下,是8000端口被其他程序占 ...
- apache(OS 10013)以一种访问权限不允许的方式做了一个访问套接字的尝试 ...
今天启动Apache时, 报了“(OS 10013)以一种访问权限不允许的方式做了一个访问套接字的尝试. : make_sock: could not bind to address 0.0.0.0: ...
- HeadFirstPython学习笔记——OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
1.文件构成如下 2.运行服务器时报错 OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试. 解决方法:更换端口 3.Python的CGI跟踪术 在 ...
随机推荐
- 11点睛Spring4.1-Property Editor
11.1 Propert Editor property editor是JavaBeans API的一项特性,用来字符和属性值之间的互相转换(如2014-03-02和Date类型的互相转换) spri ...
- k8s 使本地集群支持 LoadBalancer 服务
k8s 使本地集群支持 LoadBalancer 服务 为了使本地集群支持 LoadBalancer 服务,可以参考以下两种实现方案: keepalived-cloud-provider metalL ...
- 【GStreamer开发】GStreamer播放教程02——字幕管理
目标 这篇教程和上一篇非常相似,但不是切换音频流,而是字幕了.这次我们会展示: 如何选择选择字幕流 如何引入外部的字幕 如何客制化字幕使用的字体 介绍 我们都知道一个文件可以有多个音视频流并且可以使用 ...
- os删除文件或者文件夹
最近在使用os.remove删除目录时报错了,这里记录下os操作文件或者目录的常用方法 递归删除文件或文件夹 import shutil shutil.rmtree() 文件的重命名 os.renam ...
- 《ucore lab7》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码) 题目 完成练习0后,建议大家比较一下(可用meld等文件dif ...
- LeetCode 171. Excel表列序号(Excel Sheet Column Number) 22
171. Excel表列序号 171. Excel Sheet Column Number 题目描述 给定一个 Excel 表格中的列名称,返回其相应的列序号. 每日一算法2019/5/25Day 2 ...
- Win10使用Xmanager6远程桌面连接CentOS7服务器
服务器:CentOS 7.6 GNOME桌面环境(若最小化安装,默认是无桌面的,那么就要安装桌面,参考百度) 个人主机:Windows 10专业版,请安装Xmanager Power Suite 6( ...
- C#中HttpWebRequest、WebClient、HttpClient的使用
HttpWebRequest: 命名空间: System.Net,这是.NET创建者最初开发用于使用HTTP请求的标准类.使用HttpWebRequest可以让开发者控制请求/响应流程的各个方面,如 ...
- go语言的安装及环境配置
Go语言开发环境搭建(ubuntu) 1.清理.卸载之前的 go 语言环境: 删除go目录:sudo rm -rf /usr/local/go 删除软链接(如果建立了软链接):sudo rm -rf ...
- hadoop 完全分布式搭建总结
完全分布式--------------- 1.配置文件 [core-site.xml] hdfs 地址 fs.defaultFS=hdfs://s129:8020/ [hdfs-site.xml] 副 ...