2016-09-29 344 views
0

讓我們說我有這樣的聲明解釋:查詢C#字典使用lambda表達式

private static Dictionary<int, List<Models.APIAccessControl>> _APIRights = GetAPIRights(); 

其中關鍵代表角色ID,該值表示類:

public class APIAccessControl 
{ 
    public APIControllerRoute ControllerRoute { get; set; } 
    public APIActionRoute ActionRoute { get; set; } 
    public bool IsAuthorized { get; set; } 

} 

我試圖檢查如果用戶有權訪問此api。 我的想法是查詢字典並獲取角色的所有APIAccessControl列表,然後查詢他嘗試導航的APIActionRoute的那些APIAccessControl列表:

我得到字典值包含那些我想要角色的列表,但怎麼投值的清單列表,使此查詢:

public static bool CanAccess(int[] roleIDs, APIActionRoute apiActionRoute) 
    { 
      bool canAccess = false; 

      var apiAccessList = _APIRights.Where(x => roleIDs.Contains(x.Key)).Select(x => new { x.Value}).ToList(); 

     //Querying to get all List<Models.APIAccessControl> that has any matchig APIActionRoute 
    } 
+0

您可以嘗試使用Dictionary的Values屬性提取列表。 –

+0

你能否提供示例代碼來進行投射和查詢,我正在試圖以優雅,乾淨的方式編寫代碼。所以,如果您有任何想法,請分享您的代碼。謝謝 – Coding

+0

您必須使用apiAccessList上的循環來獲取所有ActionRoutes並將它們添加到列表中。還有其他選擇。你唯一能做的就是使用Linq。讓我知道,如果澄清任何事情 –

回答

1

您可以修改SELECT子句中給你你想要的清單:

var apiAccessList = _APIRights.Where(x => roleIDs.Contains(x.Key)) 
    .SelectMany(x => x.Value).ToList(); 

方法,不選擇匿名類和使用SelectMany,名單將是類型Models.APIAccessControl

1

這將是更好遍歷角色ID首先採取的字典查找的優勢。

bool canAccess = false; 
foreach(var roleId in roleIDs) 
{ 
    List<Models.APIAccessControl> controls; 
    if(_APIRights.TryGetValue(roleId, out controls)) 
    { 
     canAccess = controls.Any(control => control.ActionRoute.Equals(apiActionRoute)); 
     if(canAccess) 
      break; 
    } 
} 

你必須確保Equals實際上做比較,你的願望類型。默認情況下,它將是一個引用相等,如果您想要值相等,或者使用所需屬性的比較,則您必須在APIActionRoute之內重載它。

一個完全的LINQ版本雜亂

List<Models.APIAccessControl> controls; 
bool canAccess = roleIDs.Any(
    r => _APIRights.TryGetValue(r, out controls) 
      && controls.Any(
       control => control.ActionRoute.Equals(apiActionRoute))); 
1

這聽起來像你想SelectMany,突出一個「名單表」到一個列表一點點:

var apiAccessList = 
    _APIRights 
    .Where(x => roleIDs.Contains(x.Key)) 
    .SelectMany(x => x.Value) 
    .ToList(); 

,那麼你將將每個APIAccessControl對象放在一個大列表中。但它不會再按角色ID分組。它也可能有重複,這可能或可能不重要。

0

我的認爲SelectMany可能會有所幫助。

public static bool CanAccess(int[] roleIDs, APIActionRoute apiActionRoute) 
{ 
    return _APIRights.Where(x => roleIDs.Contains(x.Key)) 
     .SelectMany(x => x.Value) 
     .Any(a => a.ActionRoute == apiActionRoute); 
}