ASP.NET Core模仿中間件方式實(shí)現(xiàn)列表過濾功能
我們的很多功能當(dāng)中都會(huì)遇到對(duì)版本進(jìn)行過濾的場(chǎng)合,例如你可能需要對(duì)列表中的數(shù)據(jù)的時(shí)間進(jìn)行過濾、版本過濾、渠道以及地區(qū)信息進(jìn)行過濾。
原本的做法:設(shè)計(jì)很多個(gè)過濾方法,通過枚舉的方式組合,選擇需要過濾哪些方法,然后一個(gè)方法一個(gè)方法的調(diào)用。 這樣的做法本身沒什么問題。但是感覺很面向過程,不夠面向?qū)ο蟆?/p>
通過學(xué)習(xí).Net Core的源碼,我們可以了解到它采用了一種委托鏈表的方式,將所有的中間件都串了起來。所以我想要仿造它這個(gè)去實(shí)現(xiàn)一下這個(gè)功能。
這樣做的好處:抽象出一些過濾的方法,對(duì)于不同的系統(tǒng),只要通過Use方法,就可以增加我們的過濾規(guī)則,考慮到不同的系統(tǒng)過濾的規(guī)則不同,這樣做也比較靈活(例如 應(yīng)用管理系統(tǒng) 需要過濾版本、渠道、地區(qū) ,而黑白名單需要過濾版本、渠道、時(shí)間等等,那么對(duì)于前者我只需要在過濾的時(shí)候 UseVersion UserChannel UseArea, 對(duì)于后者把UserArea緩存UseTime即可。)
廢話不多說:上碼
1.定義一個(gè)委托類型,承載我們過濾方法
namespace FilterDelegate { public delegate IEnumerable<TcySysApplication> TcySysFilterDelegate(IEnumerable<TcySysApplication> applist, TcySysFilterConditionInfo conditionInfo ); }
委托的輸入是我們待處理的數(shù)據(jù)列表appList, 以及我們執(zhí)行過濾的條件數(shù)據(jù)。
2.定義一個(gè)Builder類,主要用于構(gòu)建我們整個(gè)過濾器,里面主要有兩個(gè)方法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.定義一堆過濾方法,這里沒有寫具體的邏輯,每一個(gè)方法都是通過Builder.Use將委托加入到委托鏈中
public static TcySysFilterBuilder UseTimeFilter(this TcySysFilterBuilder builder) { return builder.Use(next => { return (list, filterInfo) => { Console.WriteLine("我是時(shí)間過濾"); 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.執(zhí)行使用
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(); } }
圖上我使用了三種過濾,其中因?yàn)镃hannel中有過濾的邏輯,根據(jù)這個(gè)邏輯我們應(yīng)該只會(huì)返回一個(gè)Channeld = 88215的數(shù)據(jù)
我們可以將 UseChannelFilter 那句代碼注釋掉,再運(yùn)行,由于沒有過濾渠道,此時(shí)顯示了兩條數(shù)據(jù)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
詳細(xì)介紹.NET中的動(dòng)態(tài)編譯技術(shù)
這篇文章詳細(xì)介紹了.NET中的動(dòng)態(tài)編譯技術(shù),有需要的朋友可以參考一下2013-11-11ASP.NET?MVC通過勾選checkbox更改select的內(nèi)容
這篇文章介紹了ASP.NET?MVC通過勾選checkbox更改select內(nèi)容的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09在AspNetCore中使用極驗(yàn)做行為認(rèn)證的驗(yàn)證流程
這篇文章主要介紹了在AspNetCore中使用極驗(yàn)做行為認(rèn)證的驗(yàn)證流程 ,本文有圖文介紹有實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09FileUpload上傳圖片前實(shí)現(xiàn)圖片預(yù)覽功能(附演示動(dòng)畫)
FileUpload控件上傳圖片前實(shí)現(xiàn)預(yù)覽,很多網(wǎng)友都希望實(shí)現(xiàn)這樣的功能,本人總結(jié)了一下,感興趣的朋友可以參考一下,希望對(duì)您有幫助2013-01-01ASP.NET實(shí)現(xiàn)的簡(jiǎn)單易用文件上傳類
這篇文章主要介紹了ASP.NET實(shí)現(xiàn)的簡(jiǎn)單易用文件上傳類,本文給出實(shí)現(xiàn)代碼和使用方法示例,需要的朋友可以參考下2015-06-06asp.net使用DataGridTree實(shí)現(xiàn)下拉樹的方法
這篇文章主要介紹了asp.net使用DataGridTree實(shí)現(xiàn)下拉樹的方法,詳細(xì)的講述了DataGridTree實(shí)現(xiàn)下拉樹的原理與具體實(shí)現(xiàn)方法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-11-11關(guān)于.net(C#)中的跨進(jìn)程訪問的問題
C# 跨進(jìn)程訪問實(shí)現(xiàn)代碼。2009-04-04