網站首頁 編程語言 正文
我們的很多功能當中都會遇到對版本進行過濾的場合,例如你可能需要對列表中的數據的時間進行過濾、版本過濾、渠道以及地區信息進行過濾。
原本的做法:設計很多個過濾方法,通過枚舉的方式組合,選擇需要過濾哪些方法,然后一個方法一個方法的調用。 這樣的做法本身沒什么問題。但是感覺很面向過程,不夠面向對象。
通過學習.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 那句代碼注釋掉,再運行,由于沒有過濾渠道,此時顯示了兩條數據
原文鏈接:https://www.cnblogs.com/dcz2015/p/11867187.html
相關推薦
- 2022-03-28 Python垃圾回收及Linux?Fork_python
- 2023-09-17 ES常見錯誤總結
- 2022-11-22 Golang?Compare?And?Swap算法詳細介紹_Golang
- 2022-07-12 Linux環境Jenkins部署
- 2022-04-03 Python實現對相同數據分箱的小技巧分享_python
- 2022-10-03 Python中不同圖表的數據可視化的實現_python
- 2022-09-16 Android?運用@JvmName解決函數簽名沖突問題詳解_Android
- 2022-11-04 React組件化學習入門教程講解_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支