DynamicWhere.ex
DynamicWhere.exv3.4.0·docs

Cache Stores

The reflection cache is partitioned into three independent stores — each holding a different reflection artifact. Every store is a thread-safe ConcurrentDictionary with its own size cap and eviction timeline.

The three stores

StoreKeyValuePurpose
TypePropertiesTypeDictionary<string, PropertyInfo>All public instance properties per type, keyed by property name for O(1) lookup.
PropertyPath(Type, string)stringValidated & normalized dotted property paths — e.g. "customer.address.city" → "Customer.Address.City".
CollectionElementTypeTypeType?Element type for recognized collections — arrays plus exactly List<>, ICollection<>, IEnumerable<>, IList<>, HashSet<> and ISet<> — e.g. List<Order> → Order. null for everything else, IReadOnlyList<T> included.
Note
Each store is identifiable at runtime via the CacheMemoryType enum: TypeProperties, PropertyPath, and CollectionElementType. Pass that value to ClearCache or IsCacheFull to target a single store.

Targeting a specific store

using DynamicWhere.ex.Optimization.Cache.Source;
using DynamicWhere.ex.Optimization.Cache.Enums;

// Clear only the validated-path store, leave property metadata intact
CacheExpose.ClearCache(CacheMemoryType.PropertyPath);

// Check if a single store has hit its cap
bool typesFull       = CacheExpose.IsCacheFull(CacheMemoryType.TypeProperties);
bool pathsFull       = CacheExpose.IsCacheFull(CacheMemoryType.PropertyPath);
bool collectionsFull = CacheExpose.IsCacheFull(CacheMemoryType.CollectionElementType);

Sizing

All three stores share the same MaxCacheSize from your CacheOptions. The cap is a strictly-greater test, evaluated on a miss before the new entry is written, so with the default of 1000 each store settles at 1001 entries — 3003 across the process, and more when misses land concurrently. Increase or decrease this through a preset or a custom options object.

Entry lifetime

  • Entries are added on first reflection miss for a given key.
  • Entries record an access on read — a timestamp under LRU, a counter under LFU, nothing under FIFO. EvictionStrategy alone decides which; the Enable*Tracking flags do not.
  • Under LRU the timestamp is refreshed once it is a second old rather than on every read (3.3.0). Eviction only asks which entries are oldest, and an entry read a moment ago is already among the newest; writing it on every read put every thread reading the same few entries into one queue. A counter under LFU still counts every read.
  • Entries are removed only when an eviction pass runs (automatic on overflow, or manual via ForceEvictionOnAllCaches / ClearCache / ClearAllCaches).