using System.Collections; using System.Collections.Concurrent; using System.Text.RegularExpressions; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Cache; /// /// Implements on top of a concurrent dictionary. /// public class DictionaryAppCache : IRequestCache { /// /// Gets the internal items dictionary, for tests only! /// private readonly ConcurrentDictionary _items = new(); public int Count => _items.Count; /// public bool IsAvailable => true; /// public virtual object? Get(string key) => _items.TryGetValue(key, out var value) ? value : null; /// public virtual object? Get(string key, Func factory) { var value = _items.GetOrAdd(key, _ => factory()); if (value is not null) { return value; } // do not cache null values _items.TryRemove(key, out _); return null; } public bool Set(string key, object? value) => _items.TryAdd(key, value); public bool Remove(string key) => _items.TryRemove(key, out _); /// public virtual IEnumerable SearchByKey(string keyStartsWith) { var items = new List(); foreach ((string key, object? value) in _items) { if (key.InvariantStartsWith(keyStartsWith)) { items.Add(value); } } return items; } /// public IEnumerable SearchByRegex(string regex) { var compiled = new Regex(regex, RegexOptions.Compiled); var items = new List(); foreach ((string key, object? value) in _items) { if (compiled.IsMatch(key)) { items.Add(value); } } return items; } /// public virtual void Clear() => _items.Clear(); /// public virtual void Clear(string key) => _items.TryRemove(key, out _); /// public virtual void ClearOfType(Type type) => _items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == type); /// public virtual void ClearOfType() { Type typeOfT = typeof(T); ClearOfType(typeOfT); } /// public virtual void ClearOfType(Func predicate) { Type typeOfT = typeof(T); _items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value)); } /// public virtual void ClearByKey(string keyStartsWith) => _items.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)); /// public virtual void ClearByRegex(string regex) { var compiled = new Regex(regex, RegexOptions.Compiled); _items.RemoveAll(kvp => compiled.IsMatch(kvp.Key)); } public IEnumerator> GetEnumerator() => _items.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }