using Microsoft.Extensions.Azure; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Primitives; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Giants.Services.Utility { /// /// Wrapper around that caches all items of the specified type. /// /// public class SimpleMemoryCache : ISimpleMemoryCache, IDisposable { private readonly TimeSpan? expirationPeriod; private IMemoryCache memoryCache; private readonly object cacheKey; private readonly Func>> getAllItems; private CancellationTokenSource resetCacheToken; private bool disposedValue; public SimpleMemoryCache( TimeSpan? expirationPeriod, IMemoryCache memoryCache, object cacheKey, Func>> getAllItems) { this.expirationPeriod = expirationPeriod; this.memoryCache = memoryCache; this.cacheKey = cacheKey; this.getAllItems = getAllItems; this.resetCacheToken = new CancellationTokenSource(); } public async Task> GetItems() { IEnumerable items = await this.memoryCache.GetOrCreateAsync(cacheKey, this.PopulateCache); return items; } public void Invalidate() { this.resetCacheToken.Cancel(); this.resetCacheToken.Dispose(); this.resetCacheToken = new CancellationTokenSource(); } private async Task> PopulateCache(ICacheEntry cacheEntry) { if (this.expirationPeriod.HasValue) { cacheEntry.AbsoluteExpirationRelativeToNow = this.expirationPeriod; } cacheEntry.AddExpirationToken(new CancellationChangeToken(this.resetCacheToken.Token)); return await this.getAllItems(cacheEntry); } protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { this.memoryCache?.Dispose(); this.resetCacheToken?.Dispose(); } disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } }