using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace Swan.Collections { /// <summary> /// A thread-safe collection cache repository for types. /// </summary> /// <typeparam name="TValue">The type of member to cache.</typeparam> public class CollectionCacheRepository<TValue> { private readonly Lazy<ConcurrentDictionary<Type, IEnumerable<TValue>>> _data = new Lazy<ConcurrentDictionary<Type, IEnumerable<TValue>>>(() => new ConcurrentDictionary<Type, IEnumerable<TValue>>(), true); /// <summary> /// Determines whether the cache contains the specified key. /// </summary> /// <param name="key">The key.</param> /// <returns><c>true</c> if the cache contains the key, otherwise <c>false</c>.</returns> public Boolean ContainsKey(Type key) => this._data.Value.ContainsKey(key); /// <summary> /// Retrieves the properties stored for the specified type. /// If the properties are not available, it calls the factory method to retrieve them /// and returns them as an array of PropertyInfo. /// </summary> /// <param name="key">The key.</param> /// <param name="factory">The factory.</param> /// <returns> /// An array of the properties stored for the specified type. /// </returns> /// <exception cref="ArgumentNullException"> /// key /// or /// factory. /// </exception> /// <exception cref="System.ArgumentNullException">type.</exception> public IEnumerable<TValue> Retrieve(Type key, Func<Type, IEnumerable<TValue>> factory) { if(key == null) { throw new ArgumentNullException(nameof(key)); } if(factory == null) { throw new ArgumentNullException(nameof(factory)); } return this._data.Value.GetOrAdd(key, k => factory.Invoke(k).Where(item => item != null)); } } }