using System.Collections;
using System.Collections.Concurrent;
using System.Reflection;
namespace Sandbox;
///
/// Lazily performs expensive reflection, caching the result.
/// Clears itself during hotloads.
///
internal sealed class ReflectionCache : IHotloadManaged
where TKey : MemberInfo
{
[SkipHotload]
private readonly ConcurrentDictionary _cache = new();
private readonly Func _getValue;
private readonly KeyValuePair[] _defaultItems;
///
/// Creates a , wrapping a function to get a
/// lazily from a .
///
/// Expensive reflection to lazily run once per .
/// Items to initialize the cache with. Will be added again after each hotload.
public ReflectionCache( Func getValue, params KeyValuePair[] defaultItems )
{
_getValue = getValue;
_defaultItems = defaultItems;
AddDefaultItems();
}
///
/// Attempts to add the specified key and value to the .
///
/// if the item was added, if an item already had a matching key.
public bool TryAdd( TKey key, TValue value ) => _cache.TryAdd( key, value );
///
/// Gets a cached value for the given if it exists, otherwise
/// runs the expensive function wrapped by this instance and stores it.
///
public TValue this[TKey key] => _cache.GetOrAdd( key, _getValue );
private void AddDefaultItems()
{
foreach ( var item in _defaultItems )
{
_cache.TryAdd( item.Key, item.Value );
}
}
void IHotloadManaged.Persisted()
{
_cache.Clear();
AddDefaultItems();
}
}