我们的很多功能当中都会遇到对版本进行过滤的场合,例如你可能需要对列表中的数据的时间进行过滤、版本过滤、渠道以及地区信息进行过滤。

原本的做法:设计很多个过滤方法,通过枚举的方式组合,选择需要过滤哪些方法,然后一个方法一个方法的调用。 这样的做法本身没什么问题。但是感觉很面向过程,不够面向对象。

通过学习.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中间件的方式,做一个列表过滤的功能的更多相关文章

  1. 用小程序做一个类似于苹果AssistiveTouch功能

    一.首先我先介绍一下,我们要做一个什么样的项目功能 项目功能就是一个音频点击播放,当点击为播放的状态时,一个音频的动图出现,而且是可以跟随着手指的滑动而滑动,而且,在滑动动图的时候,当前下的页面是不可 ...

  2. SpringBoot2.x整合Email并利用AOP做一个项目异常通知功能

    因为不知aop能干嘛,因此用aop做个小功能,再结合最近学的springboot-Email做了个系统异常自动邮件通知的功能, 感觉满满的成就感. AOP不懂的可以看上一篇:https://www.c ...

  3. QT 创建一个具有复选功能的下拉列表控件

    最近研究了好多东西,前两天突然想做一个具有复选功能的下拉列表框.然后在网上"学习"了很久之后,终于发现了一个可以用的,特地发出来记录一下. 一.第一步肯定是先创建一个PROJECT ...

  4. [转]jsPlumb插件做一个模仿viso的可拖拉流程图

    原贴:https://www.cnblogs.com/sggx/p/3836432.html 前言 这是我第一次写博客,心情还是有点小小的激动!这次主要分享的是用jsPlumb,做一个可以给用户自定义 ...

  5. react实例之todo,做一个实时响应的列表操作

    react实例之todo, 做一个实时响应的列表操作 在所有的mvc框架中,最常见的例子不是hello world,而是todo,由于reactjs的简单性,在不引用flux和redux的情况下,我们 ...

  6. jsPlumb插件做一个模仿viso的可拖拉流程图

    前言 这是我第一次写博客,心情还是有点小小的激动!这次主要分享的是用jsPlumb,做一个可以给用户自定义拖拉的流程图,并且可以序列化保存在服务器端. 我在这次的实现上面做得比较粗糙,还有分享我在做j ...

  7. 启动django应用报错 “Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。”

    启动django应用时报如下错误 "Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试." 网上查了一下,是8000端口被其他程序占 ...

  8. apache(OS 10013)以一种访问权限不允许的方式做了一个访问套接字的尝试 ...

    今天启动Apache时, 报了“(OS 10013)以一种访问权限不允许的方式做了一个访问套接字的尝试. : make_sock: could not bind to address 0.0.0.0: ...

  9. HeadFirstPython学习笔记——OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。

    1.文件构成如下 2.运行服务器时报错 OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试. 解决方法:更换端口 3.Python的CGI跟踪术 在 ...

随机推荐

  1. Yii2性能优化

    https://www.yiiframework.com/doc/guide/2.0/zh-cn/tutorial-performance-tuning 性能优化 有许多因素影响你的 Web 应用程序 ...

  2. ubuntu 安装 svn

    sudo apt-get install subversion

  3. git当前项目免密提交

    在项目目录下,执行: vim .git/config 在url后边添加用户名密码即可 ``` [core] repositoryformatversion = filemode = true bare ...

  4. k8s ingres 的安装与使用

    1. 安装. 从ingress的官网下载yaml文件. https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy ...

  5. lnmp二级域名配置相关

    阿里云那域名解析那有误读 我在偏远的电信网选择中国联通解析死活解析不出来 以上这么配置就对了....选择默认.瞬间解析出来.... 出于对nginx 配置不够熟悉 后来一点点理出来. 不带www 也正 ...

  6. React项目使用Redux

    ⒈创建React项目 初始化一个React项目(TypeScript环境) ⒉React集成React-Router React项目使用React-Router ⒊React集成Redux Redux ...

  7. Redis的安装(windows)

    一.安装redis windows版本的下载在https://github.com/MicrosoftArchive/redis/tags msi是安装版,zip的解压就能用.建议下msi的. 下载挺 ...

  8. [C++] 二叉树计算文件单词数

    目录 前置技能 构造和遍历二叉树 文件的打开.读取和写入 需求描述 读取文件 构建二叉树 格式化输入输出 具体实现 main.cpp binarytree.h binarytree.cpp 使用二叉树 ...

  9. vector 使用pair对

    pair是一种序偶结构<x,y> 如果我们希望使用pair但又不需要map对其排序,可以在vector中使用pair对 插入pair对使用make_pair<typename,typ ...

  10. jquery中filter()和find()函数区别

    通常把这两个函数,filter()函数和find()函数称为筛选器. 下面的例子分别使用filter函数和find函数对一组列表进行筛选操作. 一组列表: <li>1</li> ...