ASP.NET Core模仿中間件方式實(shí)現(xiàn)列表過(guò)濾功能
我們的很多功能當(dāng)中都會(huì)遇到對(duì)版本進(jìn)行過(guò)濾的場(chǎng)合,例如你可能需要對(duì)列表中的數(shù)據(jù)的時(shí)間進(jìn)行過(guò)濾、版本過(guò)濾、渠道以及地區(qū)信息進(jìn)行過(guò)濾。
原本的做法:設(shè)計(jì)很多個(gè)過(guò)濾方法,通過(guò)枚舉的方式組合,選擇需要過(guò)濾哪些方法,然后一個(gè)方法一個(gè)方法的調(diào)用。 這樣的做法本身沒(méi)什么問(wèn)題。但是感覺(jué)很面向過(guò)程,不夠面向?qū)ο蟆?/p>

通過(guò)學(xué)習(xí).Net Core的源碼,我們可以了解到它采用了一種委托鏈表的方式,將所有的中間件都串了起來(lái)。所以我想要仿造它這個(gè)去實(shí)現(xiàn)一下這個(gè)功能。
這樣做的好處:抽象出一些過(guò)濾的方法,對(duì)于不同的系統(tǒng),只要通過(guò)Use方法,就可以增加我們的過(guò)濾規(guī)則,考慮到不同的系統(tǒng)過(guò)濾的規(guī)則不同,這樣做也比較靈活(例如 應(yīng)用管理系統(tǒng) 需要過(guò)濾版本、渠道、地區(qū) ,而黑白名單需要過(guò)濾版本、渠道、時(shí)間等等,那么對(duì)于前者我只需要在過(guò)濾的時(shí)候 UseVersion UserChannel UseArea, 對(duì)于后者把UserArea緩存UseTime即可。)
廢話不多說(shuō):上碼
1.定義一個(gè)委托類(lèi)型,承載我們過(guò)濾方法
namespace FilterDelegate
{
public delegate IEnumerable<TcySysApplication> TcySysFilterDelegate(IEnumerable<TcySysApplication> applist, TcySysFilterConditionInfo conditionInfo );
}委托的輸入是我們待處理的數(shù)據(jù)列表appList, 以及我們執(zhí)行過(guò)濾的條件數(shù)據(jù)。
2.定義一個(gè)Builder類(lèi),主要用于構(gòu)建我們整個(gè)過(guò)濾器,里面主要有兩個(gè)方法Use方法以及Build方法,Use方法主要用于往我們的委托列表里面增加過(guò)濾委托,Build方法主要用于生成最后的過(guò)濾器
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("過(guò)濾完成");
return applist;
};
foreach (var component in _components.Reverse())
{
last = component(last);
}
return last;
}3.定義一堆過(guò)濾方法,這里沒(méi)有寫(xiě)具體的邏輯,每一個(gè)方法都是通過(guò)Builder.Use將委托加入到委托鏈中
public static TcySysFilterBuilder UseTimeFilter(this TcySysFilterBuilder builder)
{
return builder.Use(next =>
{
return (list, filterInfo) =>
{
Console.WriteLine("我是時(shí)間過(guò)濾");
return next(list, filterInfo);
};
});
}
public static TcySysFilterBuilder UseChannelFilter(this TcySysFilterBuilder builder)
{
return builder.Use(next =>
{
return (list, filterInfo) =>
{
Console.WriteLine("我是渠道過(guò)濾");
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("我是版本過(guò)濾");
return next(list, filterInfo);
};
});
}4.其他類(lèi)型
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 ="愛(ài)玩不玩",
Version = 10001
});
sourceList.Add(new TcySysApplication
{
AppId = 1001,
ChannelId = 310200,
District = "",
City = "烏魯木齊",
Province = "新疆",
Name = "愛(ài)玩不玩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();
}
}圖上我使用了三種過(guò)濾,其中因?yàn)镃hannel中有過(guò)濾的邏輯,根據(jù)這個(gè)邏輯我們應(yīng)該只會(huì)返回一個(gè)Channeld = 88215的數(shù)據(jù)

我們可以將 UseChannelFilter 那句代碼注釋掉,再運(yùn)行,由于沒(méi)有過(guò)濾渠道,此時(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-11
ASP.NET?MVC通過(guò)勾選checkbox更改select的內(nèi)容
這篇文章介紹了ASP.NET?MVC通過(guò)勾選checkbox更改select內(nèi)容的方法,文中通過(guò)示例代碼介紹的非常詳細(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-09
FileUpload上傳圖片前實(shí)現(xiàn)圖片預(yù)覽功能(附演示動(dòng)畫(huà))
FileUpload控件上傳圖片前實(shí)現(xiàn)預(yù)覽,很多網(wǎng)友都希望實(shí)現(xiàn)這樣的功能,本人總結(jié)了一下,感興趣的朋友可以參考一下,希望對(duì)您有幫助2013-01-01
ASP.NET實(shí)現(xiàn)的簡(jiǎn)單易用文件上傳類(lèi)
這篇文章主要介紹了ASP.NET實(shí)現(xiàn)的簡(jiǎn)單易用文件上傳類(lèi),本文給出實(shí)現(xiàn)代碼和使用方法示例,需要的朋友可以參考下2015-06-06
asp.net使用DataGridTree實(shí)現(xiàn)下拉樹(shù)的方法
這篇文章主要介紹了asp.net使用DataGridTree實(shí)現(xiàn)下拉樹(shù)的方法,詳細(xì)的講述了DataGridTree實(shí)現(xiàn)下拉樹(shù)的原理與具體實(shí)現(xiàn)方法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-11-11
關(guān)于.net(C#)中的跨進(jìn)程訪問(wèn)的問(wèn)題
C# 跨進(jìn)程訪問(wèn)實(shí)現(xiàn)代碼。2009-04-04

