参考:.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