You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 7中MemoryCache获取EntriesCollection属性返回null的解决方法

问题描述

我有一段在.NET 6环境下运行正常的代码,升级至.NET 7后无法正常工作。核心问题是typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance)始终返回null。原代码如下:

// Get the empty definition for the EntriesCollection
var cacheEntriesCollectionDefinition = typeof(MemoryCache).GetProperty("EntriesCollection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

if (cacheEntriesCollectionDefinition!=null)
{
    // Populate the definition with your IMemoryCache instance.  
    // It needs to be cast as a dynamic, otherwise you can't
    // loop through it due to it being a collection of objects.
    var cacheEntriesCollection = cacheEntriesCollectionDefinition.GetValue(_cache) as dynamic;

    if (cacheEntriesCollection!=null)
    {
        // Define a new list we'll be adding the cache entries too
        List<ICacheEntry> cacheCollectionValues = new List<ICacheEntry>();

        foreach (var cacheItem in cacheEntriesCollection)
        {
            // Get the "Value" from the key/value pair which contains the cache entry   
            ICacheEntry cacheItemValue = cacheItem.GetType().GetProperty("Value").GetValue(cacheItem, null);

            // Add the cache entry to the list
            cacheCollectionValues.Add(cacheItemValue);
        }

        
        var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
        var keysToRemove = cacheCollectionValues.Where(d => regex.IsMatch(d.Key.ToString())).Select(d => d.Key).ToList();

        foreach (var key in keysToRemove)
        {
            _cache.Remove(key);
        }
    }
}
修复方案

.NET 7对MemoryCache的内部实现做了调整,移除了原有的EntriesCollection私有属性,改用_entries私有字段存储缓存条目集合。你需要修改反射逻辑,从获取属性改为获取字段,再直接处理内部的字典结构:

using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Caching.Memory;

// 获取MemoryCache内部的_entries私有字段
var entriesField = typeof(MemoryCache).GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance);
if (entriesField != null)
{
    // _entries的实际类型是ConcurrentDictionary<object, CacheEntry>,这里先转为通用字典类型
    var entries = entriesField.GetValue(_cache) as System.Collections.Concurrent.ConcurrentDictionary<object, object>;
    if (entries != null)
    {
        var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
        // 直接遍历字典的键,匹配后收集需要删除的键
        var keysToRemove = entries.Keys.Where(key => regex.IsMatch(key.ToString())).ToList();

        foreach (var key in keysToRemove)
        {
            _cache.Remove(key);
        }
    }
}

重要提示

  • 依赖私有成员的反射实现不具备长期兼容性,微软可能在后续.NET版本中再次修改内部结构,导致代码失效。
  • 推荐的替代方案是在添加缓存时自行维护缓存键的集合(比如用ConcurrentHashSet或ConcurrentDictionary),清理时直接遍历这个集合,完全避免反射操作,这样代码更稳定可靠。

内容的提问来源于stack exchange,提问作者volkan topal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 02:06:25