2016-09-29 2 views
0

Let‘sagen, ich habe diese erklärt Wörterbuch:Querying C# Wörterbuch mit Lambda-Ausdrücke

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

Wo der Schlüssel für den RoleID repräsentiert, repräsentiert der Wert die Klasse:

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

} 

Ich versuche, zu überprüfen, wenn der Benutzer berechtigt ist, auf diese API zuzugreifen. Meine Idee ist, das Wörterbuch abzufragen und alle Liste von APIAccessControl für die Rollen, dann Abfragen dieser APIAccessControl-Listen für die APIActionRoute, die er versucht zu navigieren:

Ich habe die Wörterbuchwerte, die diese Liste für die Rollen, die ich will , aber wie eine Liste von Werten zu werfen, diese Abfrage Liste und macht:

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

Sie können versuchen, die Liste mithilfe der Values-Eigenschaft von Dictionary zu extrahieren. –

+0

können Sie Beispielcode für das Casting und Abfrage bereitstellen, ich versuche, es auf elegante, saubere Weise zu schreiben. Also, wenn Sie irgendwelche Gedanken haben, teilen Sie bitte Ihren Code. Danke – Coding

+0

Sie müssen eine Schleife über apiAccessList verwenden, um alle ActionRoutes zu erhalten und sie in einer Liste hinzuzufügen. Es gibt eine Alternative. Das einzige, was Sie tun können, ist Linq zu verwenden. Lass es mich wissen, wenn das etwas klarstellt –

Antwort

1

Sie können die Select-Klausel ändern, um Ihnen die Liste, die Sie wollen:

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

Durch die nicht zu einer anonymen Klasse auswählen und durch die SelectMany verwenden, wird die Liste der Typ sein Models.APIAccessControl

1

Es wäre besser, die Rolle iterieren ids ersten Vorteile des Wörterbücher Nachschlag zu nehmen.

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; 
    } 
} 

Sie werden sicher Equals machen müssen tatsächlich tut die Art des Vergleichs, dass Sie sich wünschen. Standardmäßig wird es eine Referenzgleichheit sein, und Sie müssten es in APIActionRoute überladen, wenn Sie Wertgleichheit wünschen, oder stattdessen einen Vergleich der gewünschten Eigenschaften verwenden.

Eine völlig Linq-Version ist ein wenig chaotisch

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

Es klingt wie Sie SelectMany wollen, die eine „Liste von Listen“ in einer einzigen Liste Projekte:

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

Sie werden dann habe jedes APIAccessControl Objekt in einer großen Liste. Es würde jedoch nicht mehr nach roleID gruppiert. Es könnte auch Duplikate haben, die wichtig sind oder nicht.

0

I denke, die SelectMany kann helfen.

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); 
}