Ich habe eine Liste von Berechtigungen. Eine Berechtigungsklasse verfügt über vier Eigenschaften: Typ, AccessType, Wert und Aktion. Ich möchte eine Ausnahme auslösen, wenn es mehrere Berechtigungen gibt, bei denen Typ, Zugriffstyp und Wert gleich sind, ABER die Aktionen sind unterschiedlich.
So würde beispielsweise eine Liste von p1 und p2 eine Ausnahme auslösen:
Privilege p1 = new Privilege{Type = "a", AccessType = "a", Value = "a", Action = "a"};
Privilege p2 = new Privilege{Type = "a", AccessType = "a", Value = "a", Action = "b"};
Ich würde gerne LINQ verwenden, bin mir aber nicht sicher, wie.
4 Antworten
Sie möchten also einen doppelten Typ + Zugriffstyp + Wert zulassen, aber nur, wenn die Aktion auch dieselbe ist?
bool throwException = pList
.GroupBy(x => new { x.Type, x.AccessType, x.Value })
.Any(g => g.Select(p => p.Action).Distinct().Count() > 1);
Zuerst baue ich Gruppen dieser drei Eigenschaften. Dann überprüfe ich, ob eine dieser Gruppen mehrere Aktionen enthält. Dann können Sie die Ausnahme auslösen.
Eine kleine Optimierung kann sein (wenn die doppelten Listen groß sind), wenn Sie ersetzen
Distinct().Count() > 1
Mit
Distinct().Skip(1).Any()
Es klingt so, als ob Sie nach Type
, AccessType
und Value
gruppieren möchten (was Sie mit einem anonymen Typ tun können) und dann die Aktionen überprüfen möchten. Angenommen, es ist in Ordnung, Werte zu haben, bei denen Action
in jedem Fall gleich ist, könnten Sie Code wie folgt schreiben:
// Normally I'd expect you to have some kind of sequence of privileges rather
// than separate variables.
var privileges = new[] { p1, p2 };
var failures = privileges
// Group the privileges by 3 properties, extracting actions as the values
.GroupBy(p => new { p.Type, p.AccessType, p.Value }, p => p.Action)
// Find any groups which have more than one distinct action
.Where(g => g.Distinct().Skip(1).Any())
.ToList();
if (failures.Count > 0)
{
// There's at least one failure. There may be many. Throw
// whatever exception you want here. This is just an example.
var individualMessages =
failures.Select(g => $"{g.Key}: {string.Join(", ", g.Distinct())}");
throw new Exception(
$"Invalid privilege combinations: {string.Join("; ", individualMessages})");
}
Hier ist ein vollständiges Beispiel, das einige Fehler zeigt:
using System;
using System.Collections.Generic;
using System.Linq;
class Privilege
{
public string Type { get; }
public string AccessType { get; }
public string Value { get; }
public string Action { get; }
public Privilege(string type, string accessType, string value, string action)
{
Type = type;
AccessType = accessType;
Value = value;
Action = action;
}
}
class Test
{
static void Main()
{
var privileges = new List<Privilege>
{
// Bad: should cause an exception
new Privilege("a", "a", "a", "a"),
new Privilege("a", "a", "a", "b"),
// Another bad one; let's check the
// failure represents both
new Privilege("x", "y", "z", "action1"),
new Privilege("x", "y", "z", "action2"),
// These have one property difference
// in each case
new Privilege("b", "a", "a", "a"),
new Privilege("a", "b", "a", "a"),
new Privilege("a", "a", "b", "a"),
// Duplicate type/access/value, but same action too.
new Privilege("d", "e", "f", "action"),
new Privilege("d", "e", "f", "action")
};
CheckPrivileges(privileges);
}
static void CheckPrivileges(IEnumerable<Privilege> privileges)
{
var failures = privileges
// Group the privileges by 3 properties, extracting actions as the values
.GroupBy(p => new { p.Type, p.AccessType, p.Value }, p => p.Action)
// Find any groups which have more than one distinct action
.Where(g => g.Distinct().Skip(1).Any())
.ToList();
if (failures.Count > 0)
{
// There's at least one failure. There may be many. Throw
// whatever exception you want here. This is just an example.
var individualMessages =
failures.Select(g => $"{g.Key}: {string.Join(", ", g.Distinct())}");
throw new Exception(
$"Invalid privilege combinations: {string.Join("; ", individualMessages)}");
}
}
}
Dies erzeugt eine Ausnahme wie diese (ich habe die Zeilenumbrüche hinzugefügt):
Unhandled Exception: System.Exception: Invalid privilege combinations:
{ Type = a, AccessType = a, Value = a }: a, b;
{ Type = x, AccessType = y, Value = z }: action1, action2
var duplicates = privilegecollection.GroupBy(x => new {x.Type, x.AccessType, x.Value})
.Where(g => g.Count() > 1)
.Select(g => g.Key);
Wenn die Anzahl duplicates
größer als 0 ist, können Sie eine Ausnahme auslösen.
Ich denke, die einfachste Lösung besteht darin, 2 Any()
zu verwenden.
bool HasDoubleOtherAction = privilegeList.Any(outer => privilegeList
.Any(inner => outer.Type == inner.Type
&& outer.AccessType == inner.AccessType
&& outer.Value == inner.Value
&& outer.Action != inner.Action));
Neue Fragen
c#
C # (ausgesprochen "siehe scharf") ist eine statische Typisierungsprogrammiersprache mit mehreren Paradigmen, die von Microsoft entwickelt wurde. C # -Code zielt normalerweise auf die .NET-Tools und -Laufzeiten von Microsoft ab, zu denen unter anderem .NET Framework, .NET Core und Xamarin gehören. Verwenden Sie dieses Tag für Fragen zu Code, der in der formalen Spezifikation von C # oder C # geschrieben ist.