===============================================
2020/2/29_第1次修改 ccb_warlock
===============================================
最近優化了一個權限校驗的功能,之前每次其他系統在獲取各自系統的權限配置時,sso都去找到本地對應的權限文件讀取解析一次。
這種設計雖然可以實現功能,但是這種反復去讀取的策略並不經濟,尤其在高並發的情況下更可能會成為性能瓶頸。
於是我對這塊業務進行了優化,而在優化的過程中針對如何去除數組內的某些參數試驗了一些寫法,下面記錄我認為比較優雅的寫法。
首先講下場景,設計多系統的權限統一由sso控制,那么每次用戶登錄其他系統后需要向sso請求“用戶在該系統已有的權限”或“該用戶當前是否擁有該功能的操作權限”。
那么sso需要在權限驗證通過后再去獲取該用戶當前的權限信息並返回,於是在權限校驗的service中,我在構造器里根據已有的系統類型先獲取一次對應完整的權限樹,后面如果發現有缺失再嘗試讀取文件,不缺失則直接讀緩存配置。
已有的系統通過枚舉來記錄,假設定義如下:
public enum EnumSystemType { NoMenu = 0, // 不需要權限樹的系統或程序 App01 = 1, App02 = 2, ...... }
每個系統的權限配置保存在各自的文件中,例如App01完整的權限樹保存在App01.json中。
接着就是根據已有的系統去獲取每個文件的內容並解析成權限樹緩存下來。而在獲取文件內容時,不需要獲取權限的枚舉(NoMenu)需要跳過找文件讀取的邏輯。這里我借助的是linq的功能來實現過濾該枚舉值的邏輯。
using System.Linq; private Dictionary<string, List<PermissionNode>> GetPermissions() { //todo foreach (var fileName in Enum.GetNames(typeof(EnumSystemType)) .Where(s => s != nameof(EnumSystemType.NoMenu)) .ToArray()) { //todo } //todo }
PS. Enum.GetNames的返回值是字符串數組。
單個參數的過濾通過where很容易就實現了,我突然想到一個問題,如何實現批量過濾一些枚舉值呢?
查了查資料,linq果然有解決方案,就是通過“Except”。
接着我還是以上面的例子來試驗,假如我希望構造器讀取時跳過NoMenu和App01,可以這么寫:
using System.Linq; private Dictionary<string, List<PermissionNode>> GetPermissions() { //todo var exceptPermissions = new [] { nameof(EnumSystemType.NoMenu), nameof(EnumSystemType.App01), }; foreach (var fileName in Enum.GetNames(typeof(EnumSystemType)) .Except(exceptPermissions) .ToArray()) { //todo } //todo }
總結:
1. 如何在一個數組中移除某個值的寫法:linq的where
2. 如何在一個數組中移除多個值的寫法:linq的except