【问题标题】:Querying C# Dictionary using Lambda expressions使用 Lambda 表达式查询 C# 字典
【发布时间】:2016-09-29 15:58:14
【问题描述】:

假设我有这个声明字典:

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

其中key代表roleId,value代表class:

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

}

我正在尝试检查用户是否有权访问此 api。 我的想法是查询字典并获取角色的所有 APIAccessControl 列表,然后查询那些 APIAccessControl 列表以查找他试图导航的 APIActionRoute:

我得到了包含我想要的角色列表的字典值,但是如何将值列表转换为列表并进行以下查询:

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
    }

【问题讨论】:

  • 您可以尝试使用 Dictionary 的 Values 属性提取列表。
  • 您能否提供示例代码来进行转换和查询,我正在尝试以优雅、干净的方式编写它。因此,如果您有任何想法,请分享您的代码。谢谢
  • 您必须在 apiAccessList 上使用循环来获取所有 ActionRoutes 并将它们添加到列表中。有替代方案。你唯一能做的就是使用 Linq。让我知道这是否可以澄清任何事情

标签: c# linq dictionary lambda


【解决方案1】:

您可以修改 Select 子句以提供您想要的列表:

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

通过不选择匿名类并使用SelectMany,列表的类型为Models.APIAccessControl

【讨论】:

    【解决方案2】:

    最好先遍历角色 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)));
    

    【讨论】:

      【解决方案3】:

      听起来你想要SelectMany,它将“列表列表”投影到单个列表中:

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

      然后,您将在一个大列表中包含每个 APIAccessControl 对象。不过,它将不再按角色 ID 分组。它也可能有重复,这可能重要也可能不重要。

      【讨论】:

        【解决方案4】:

        我认为 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);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多