QueryKey

Ein strukturierter, geordneter Cache-Key mit Wertgleichheit auf einer kanonischen Form. Die Reihenfolge der Segmente zählt; Dictionary-Segmente werden durch Sortieren ihrer Keys normalisiert.

public sealed class QueryKey : IEquatable<QueryKey>

Member#

Of#

public static QueryKey Of(params object?[] segments)

Erstellt einen Key aus geordneten Segmenten: QueryKey.Of("todos", "detail", 5). Unterstützte Segmenttypen: Strings, numerische Primitive, bool, char, Guid, DateTime, DateTimeOffset, DateOnly, TimeOnly, TimeSpan, Enums, null, Collections daraus, Dictionaries mit String-Keys sowie jeder Typ, der IQueryKeySegment implementiert. Wirft ArgumentException bei fehlenden Segmenten oder einem nicht unterstützten Segmenttyp — lautes Scheitern an der Aufrufstelle ist besser als ein stillschweigend kollidierender Cache-Eintrag.

FromString#

public static QueryKey? FromString(string? key)

Das benannte Gegenstück zur impliziten String-Konvertierung. Null oder reiner Whitespace ergibt null — kein Key.

implicit operator#

public static implicit operator QueryKey?(string? key)

Hält QueryKey = "todos"-Aufrufstellen kompilierbar — mit der Bedeutung QueryKey.Of("todos"). Null oder Whitespace konvertiert zu null — kein Key.

StartsWith#

public bool StartsWith(QueryKey prefix)

True, wenn die führenden Segmente dieses Keys jedem Segment von prefix entsprechen — ["todos", 1] beginnt mit ["todos"]. Verglichen wird Segment für Segment auf kanonischen Formen, nie als String-Präfix des gesamten Hashes; ["todo"] passt daher nicht auf ["todos"].

Equality#

public bool Equals(QueryKey? other) public static bool operator ==(QueryKey? left, QueryKey? right) public static bool operator !=(QueryKey? left, QueryKey? right) public override int GetHashCode()

Wertgleichheit auf der kanonischen Form.

ToString#

public override string ToString()

Die kanonische Form, z. B. ["todos",{"page":2}].

Kanonisierungsregeln#

  • Strings werden in Anführungszeichen gesetzt und escapet, sodass ["a,b"] und ["a","b"] nicht kollidieren können.
  • Zahlen, Datums- und Zeitwerte verwenden die invariante Culture.
  • Enums verwenden ihren numerischen Wert — ein Member kann umbenannt werden, ohne die gecachte Identität stillschweigend zu ändern.
  • Dictionaries müssen String-Keys haben und werden mit Keys in ordinaler Reihenfolge geschrieben; die Reihenfolge der Properties in einem Ad-hoc-Filterobjekt ändert die Identität also nicht.
  • Collections verschachteln sich, bis zu einer maximalen Tiefe von 32 (schützt vor zyklischen Graphen).
  • Von Hand berechnet statt mit einem JSON-Serializer — das hält das Paket frei von Abhängigkeiten sowie trimming- und AOT-sicher.

IQueryKeySegment#

IQueryKeySegment#

public interface IQueryKeySegment { string ToKeySegment(); }

Erlaubt einem eigenen Typ, als Key-Segment teilzunehmen. ToKeySegment() muss einen stabilen, deterministischen String zurückgeben: gleiche Werte gleiche Strings, unterschiedliche Werte unterschiedliche Strings, über Sessions hinweg — er geht direkt in die Identität des Keys ein. Bewusst ein Interface statt Reflection über beliebige Objekte: Das Key-Hashing läuft bei jedem Cache-Lookup und muss trimming- und AOT-sicher bleiben. Anonyme Typen können deshalb keine Segmente sein — verwende ein Dictionary<string, object?> oder einen benannten Typ, der dieses Interface implementiert.