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#
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#
Das benannte Gegenstück zur impliziten String-Konvertierung. Null oder reiner Whitespace ergibt null — kein Key.
implicit operator#
Hält QueryKey = "todos"-Aufrufstellen kompilierbar — mit der Bedeutung
QueryKey.Of("todos"). Null oder Whitespace konvertiert zu null — kein
Key.
StartsWith#
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#
Wertgleichheit auf der kanonischen Form.
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#
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.