首页 > 其他分享 >MemoryCache 7.0 可用的获取所有Key的方法

MemoryCache 7.0 可用的获取所有Key的方法

时间:2023-02-27 00:22:10浏览次数:47  
标签:MemoryCache ._ coherentState 7.0 Key entries entry priorEntry

参考:.NET Core MemoryCache缓存获取全部缓存键 - stone8386 - 博客园 (cnblogs.com)

根据参考所述方法获取Key出错,提示 _entries 为null,后搜索无果,通过vs自带反编译查看MemoryCache,也并没有发现 “_entries ”字段。然后发现了一段方法内“coherentState._entries.TryGetValue”:

 

  1 internal void SetEntry(CacheEntry entry)
  2         {
  3             if (_disposed)
  4             {
  5                 // No-op instead of throwing since this is called during CacheEntry.Dispose
  6                 return;
  7             }
  8 
  9             if (_options.HasSizeLimit && entry.Size < 0)
 10             {
 11                 throw new InvalidOperationException(SR.Format(SR.CacheEntryHasEmptySize, nameof(entry.Size), nameof(_options.SizeLimit)));
 12             }
 13 
 14             DateTime utcNow = UtcNow;
 15 
 16             // Applying the option's absolute expiration only if it's not already smaller.
 17             // This can be the case if a dependent cache entry has a smaller value, and
 18             // it was set by cascading it to its parent.
 19             if (entry.AbsoluteExpirationRelativeToNow.Ticks > 0)
 20             {
 21                 long absoluteExpiration = (utcNow + entry.AbsoluteExpirationRelativeToNow).Ticks;
 22                 if ((ulong)absoluteExpiration < (ulong)entry.AbsoluteExpirationTicks)
 23                 {
 24                     entry.AbsoluteExpirationTicks = absoluteExpiration;
 25                 }
 26             }
 27 
 28             // Initialize the last access timestamp at the time the entry is added
 29             entry.LastAccessed = utcNow;
 30 
 31             CoherentState coherentState = _coherentState; // Clear() can update the reference in the meantime
 32             if (coherentState._entries.TryGetValue(entry.Key, out CacheEntry? priorEntry))
 33             {
 34                 priorEntry.SetExpired(EvictionReason.Replaced);
 35             }
 36 
 37             if (entry.CheckExpired(utcNow))
 38             {
 39                 entry.InvokeEvictionCallbacks();
 40                 if (priorEntry != null)
 41                 {
 42                     coherentState.RemoveEntry(priorEntry, _options);
 43                 }
 44             }
 45             else if (!UpdateCacheSizeExceedsCapacity(entry, coherentState))
 46             {
 47                 bool entryAdded;
 48                 if (priorEntry == null)
 49                 {
 50                     // Try to add the new entry if no previous entries exist.
 51                     entryAdded = coherentState._entries.TryAdd(entry.Key, entry);
 52                 }
 53                 else
 54                 {
 55                     // Try to update with the new entry if a previous entries exist.
 56                     entryAdded = coherentState._entries.TryUpdate(entry.Key, entry, priorEntry);
 57 
 58                     if (entryAdded)
 59                     {
 60                         if (_options.HasSizeLimit)
 61                         {
 62                             // The prior entry was removed, decrease the by the prior entry's size
 63                             Interlocked.Add(ref coherentState._cacheSize, -priorEntry.Size);
 64                         }
 65                     }
 66                     else
 67                     {
 68                         // The update will fail if the previous entry was removed after retrieval.
 69                         // Adding the new entry will succeed only if no entry has been added since.
 70                         // This guarantees removing an old entry does not prevent adding a new entry.
 71                         entryAdded = coherentState._entries.TryAdd(entry.Key, entry);
 72                     }
 73                 }
 74 
 75                 if (entryAdded)
 76                 {
 77                     entry.AttachTokens();
 78                 }
 79                 else
 80                 {
 81                     if (_options.HasSizeLimit)
 82                     {
 83                         // Entry could not be added, reset cache size
 84                         Interlocked.Add(ref coherentState._cacheSize, -entry.Size);
 85                     }
 86                     entry.SetExpired(EvictionReason.Replaced);
 87                     entry.InvokeEvictionCallbacks();
 88                 }
 89 
 90                 priorEntry?.InvokeEvictionCallbacks();
 91             }
 92             else
 93             {
 94                 entry.SetExpired(EvictionReason.Capacity);
 95                 TriggerOvercapacityCompaction();
 96                 entry.InvokeEvictionCallbacks();
 97                 if (priorEntry != null)
 98                 {
 99                     coherentState.RemoveEntry(priorEntry, _options);
100                 }
101             }
102 
103             StartScanForExpiredItemsIfNeeded(utcNow);
104         }

 

原来在新版本中“_entries”转移到了“private CoherentState _coherentState;”这个字段内了。遂更改代码:

 1 public List<string> GetCacheKeys()
 2         {
 3             const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
 4             var coherentState = Cache.GetType().GetField("_coherentState", flags).GetValue(Cache);//增加一个获取CoherentState对象环节
 5             var entries = coherentState.GetType().GetField("_entries", flags).GetValue(coherentState);
 6             var cacheItems = entries as IDictionary;
 7             var keys = new List<string>();
 8             if (cacheItems == null) return keys;
 9             foreach (DictionaryEntry cacheItem in cacheItems)
10             {
11                 keys.Add(cacheItem.Key.ToString());
12             }
13             return keys;
14         }

测试通过!

 

标签:MemoryCache,._,coherentState,7.0,Key,entries,entry,priorEntry
From: https://www.cnblogs.com/tiomer/p/17158305.html

相关文章