读取MemoryCache的内容,包括到期时间

时间:2015-10-14 05:19:21

标签: c# c#-4.0 reflection memorycache

是否可以提取MemoryCache对象的内容,包括:

  1. 缓存商品密钥
  2. 缓存项目值
  3. 缓存项目到期时间 ?

1 个答案:

答案 0 :(得分:0)

提取缓存项目键和值很简单,并在Internet上的其他地方介绍。经过一些研究后,似乎方法为每个项目提取到期时间。我们必须使用Reflection,因为框架不会公开MemoryCache的内部对象。

我们将首先创建一个类来存储每个缓存项的信息:​​

    public class MemoryCacheItemInfo
    {
        public string Key { get; private set; }
        public object CacheItemValue { get; private set; }
        public DateTime Created { get; private set; }
        public DateTime LastUpdateUsage { get; private set; }
        public DateTime AbsoluteExpiry { get; private set; }
        public TimeSpan SlidingExpiry { get; private set; }

        public MemoryCacheItemInfo(string key, object cacheItemValue,
            DateTime created, DateTime lastUpdateUsage, DateTime absoluteExpiry,
            TimeSpan slidingExpiry)
        {
            this.Key = key;
            this.CacheItemValue = cacheItemValue;
            this.Created = created;
            this.LastUpdateUsage = lastUpdateUsage;
            this.AbsoluteExpiry = absoluteExpiry;
            this.SlidingExpiry = slidingExpiry;
        }
    }

现在,我们将使用Reflection访问私有MemoryCache字段:

    public static MemoryCacheItemInfo[] GetCacheItemInfo(this MemoryCache cache)
    {
        BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

        FieldInfo field = typeof (MemoryCache).GetField("_stores", bindFlags);
        object[] cacheStores = (object[]) field.GetValue(cache);

        List<MemoryCacheItemInfo> info = new List<MemoryCacheItemInfo>();

        foreach (object cacheStore in cacheStores)
        {
            Type cacheStoreType = cacheStore.GetType();

            FieldInfo lockField = cacheStoreType.GetField("_entriesLock", bindFlags);

            object lockObj = lockField.GetValue(cacheStore);

            lock (lockObj)
            {

                FieldInfo entriesField = cacheStoreType.GetField("_entries", bindFlags);
                Hashtable entriesCollection = (Hashtable) entriesField.GetValue(cacheStore);

                foreach (DictionaryEntry cacheItemEntry in entriesCollection)
                {
                    Type cacheItemValueType = cacheItemEntry.Value.GetType();

                    string key = (string) cacheItemEntry.Key.GetType().GetProperty("Key", bindFlags).GetValue(cacheItemEntry.Key);

                    PropertyInfo value = cacheItemValueType.GetProperty("Value", bindFlags);
                    PropertyInfo utcCreated = cacheItemValueType.GetProperty("UtcCreated", bindFlags);
                    PropertyInfo utcLastUpdateUsage = cacheItemValueType.GetProperty("UtcLastUpdateUsage", bindFlags);
                    PropertyInfo utcAbsoluteExpiry = cacheItemValueType.GetProperty("UtcAbsExp", bindFlags);
                    PropertyInfo utcSlidingExpiry = cacheItemValueType.GetProperty("SlidingExp", bindFlags);

                    MemoryCacheItemInfo mcii = new MemoryCacheItemInfo(
                        key,
                        value.GetValue(cacheItemEntry.Value),
                        ((DateTime) utcCreated.GetValue(cacheItemEntry.Value)).ToLocalTime(),
                        ((DateTime) utcLastUpdateUsage.GetValue(cacheItemEntry.Value)).ToLocalTime(),
                        ((DateTime) utcAbsoluteExpiry.GetValue(cacheItemEntry.Value)).ToLocalTime(),
                        ((TimeSpan) utcSlidingExpiry.GetValue(cacheItemEntry.Value))
                        );

                    info.Add(mcii);
                }

            }
        }

        return info.ToArray();
    }

此方法效率不高,不建议用于生产环境。

此外,Microsoft未正式支持访问MemoryCache个私有字段。 MemoryCache对象的内部结构将来可能会发生变化,这将破坏此代码。