Asp.net-Core

ASP.NET Core 從 IMemoryCache 清除記憶體(由 CacheExtensions 類的 Set 方法設置)

  • May 10, 2022

乍一看,這看起來與這個問題重複,但我不是在問如何清除 EF 的記憶體。

如何清除IMemoryCache介面設置的整個記憶體?

   public CacheService(IMemoryCache memoryCache) 
   {
       this._memoryCache = memoryCache;
   }

   public async Task<List<string>> GetCacheItem()
   {
       if (!this._memoryCache.TryGetValue("Something", out List<string> list))
       {
           list= await this ...

           this._memoryCache.Set("Something", list, new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.NeverRemove));
       }

       return list;
   }

這只是一個例子。我有許多將值儲存到記憶體的類/方法。現在我需要將它們全部刪除。

在某些情況下,我的密鑰是動態創建的,所以我不知道需要刪除哪些密鑰。清除將是完美的。

我可以編寫自己的內部使用的介面和類IMemoryCache,但這似乎有點矯枉過正。有沒有更簡單的選擇?

因為我找不到任何好的解決方案,所以我自己編寫。

在 SamiAl90 解決方案(答案)中,我錯過了ICacheEntry介面中的所有屬性。

它在內部使用IMemoryCache

案例與 2 個附加功能完全相同:

  1. 從記憶體記憶體中清除所有項目
  2. 遍歷所有鍵/值對

您必須註冊單身人士:

serviceCollection.AddSingleton<IMyCache, MyMemoryCache>();

案例:

public MyController(IMyCache cache)
{
   this._cache = cache;
}

[HttpPut]
public IActionResult ClearCache()
{
   this._cache.Clear();
   return new JsonResult(true);
}

[HttpGet]
public IActionResult ListCache()
{
   var result = this._cache.Select(t => new
   {
       Key = t.Key,
       Value = t.Value
   }).ToArray();
   return new JsonResult(result);
}

資源:

public interface IMyCache : IEnumerable<KeyValuePair<object, object>>, IMemoryCache
{
   /// <summary>
   /// Clears all cache entries.
   /// </summary>
   void Clear();
}

public class MyMemoryCache : IMyCache
{
   private readonly IMemoryCache _memoryCache;
   private readonly ConcurrentDictionary<object, ICacheEntry> _cacheEntries = new ConcurrentDictionary<object, ICacheEntry>();

   public MyMemoryCache(IMemoryCache memoryCache)
   {
       this._memoryCache = memoryCache;
   }

   public void Dispose()
   {
       this._memoryCache.Dispose();
   }

   private void PostEvictionCallback(object key, object value, EvictionReason reason, object state)
   {
       if (reason != EvictionReason.Replaced)
           this._cacheEntries.TryRemove(key, out var _);
   }

   /// <inheritdoc cref="IMemoryCache.TryGetValue"/>
   public bool TryGetValue(object key, out object value)
   {
       return this._memoryCache.TryGetValue(key, out value);
   }

   /// <summary>
   /// Create or overwrite an entry in the cache and add key to Dictionary.
   /// </summary>
   /// <param name="key">An object identifying the entry.</param>
   /// <returns>The newly created <see cref="T:Microsoft.Extensions.Caching.Memory.ICacheEntry" /> instance.</returns>
   public ICacheEntry CreateEntry(object key)
   {
       var entry = this._memoryCache.CreateEntry(key);
       entry.RegisterPostEvictionCallback(this.PostEvictionCallback);
       this._cacheEntries.AddOrUpdate(key, entry, (o, cacheEntry) =>
       {
           cacheEntry.Value = entry;
           return cacheEntry;
       });
       return entry;
   }

   /// <inheritdoc cref="IMemoryCache.Remove"/>
   public void Remove(object key)
   {
       this._memoryCache.Remove(key);
   }

   /// <inheritdoc cref="IMyCache.Clear"/>
   public void Clear()
   {
       foreach (var cacheEntry in this._cacheEntries.Keys.ToList())
           this._memoryCache.Remove(cacheEntry);
   }

   public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
   {
       return this._cacheEntries.Select(pair => new KeyValuePair<object, object>(pair.Key, pair.Value.Value)).GetEnumerator();
   }

   IEnumerator IEnumerable.GetEnumerator()
   {
       return this.GetEnumerator();
   }

   /// <summary>
   /// Gets keys of all items in MemoryCache.
   /// </summary>
   public IEnumerator<object> Keys => this._cacheEntries.Keys.GetEnumerator();
}

public static class MyMemoryCacheExtensions
{
   public static T Set<T>(this IMyCache cache, object key, T value)
   {
       var entry = cache.CreateEntry(key);
       entry.Value = value;
       entry.Dispose();

       return value;
   }

   public static T Set<T>(this IMyCache cache, object key, T value, CacheItemPriority priority)
   {
       var entry = cache.CreateEntry(key);
       entry.Priority = priority;
       entry.Value = value;
       entry.Dispose();

       return value;
   }

   public static T Set<T>(this IMyCache cache, object key, T value, DateTimeOffset absoluteExpiration)
   {
       var entry = cache.CreateEntry(key);
       entry.AbsoluteExpiration = absoluteExpiration;
       entry.Value = value;
       entry.Dispose();

       return value;
   }

   public static T Set<T>(this IMyCache cache, object key, T value, TimeSpan absoluteExpirationRelativeToNow)
   {
       var entry = cache.CreateEntry(key);
       entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow;
       entry.Value = value;
       entry.Dispose();

       return value;
   }

   public static T Set<T>(this IMyCache cache, object key, T value, MemoryCacheEntryOptions options)
   {
       using (var entry = cache.CreateEntry(key))
       {
           if (options != null)
               entry.SetOptions(options);

           entry.Value = value;
       }

       return value;
   }

   public static TItem GetOrCreate<TItem>(this IMyCache cache, object key, Func<ICacheEntry, TItem> factory)
   {
       if (!cache.TryGetValue(key, out var result))
       {
           var entry = cache.CreateEntry(key);
           result = factory(entry);
           entry.SetValue(result);
           entry.Dispose();
       }

       return (TItem)result;
   }

   public static async Task<TItem> GetOrCreateAsync<TItem>(this IMyCache cache, object key, Func<ICacheEntry, Task<TItem>> factory)
   {
       if (!cache.TryGetValue(key, out object result))
       {
           var entry = cache.CreateEntry(key);
           result = await factory(entry);
           entry.SetValue(result);
           entry.Dispose();
       }

       return (TItem)result;
   }
}

引用自:https://stackoverflow.com/questions/49176244