【问题标题】:How can I get the expiry datetime of an HttpRuntime.Cache object?如何获取 HttpRuntime.Cache 对象的到期日期时间?
【发布时间】:2010-09-25 13:27:31
【问题描述】:

是否可以获得DateTime 对象的到期时间HttpRuntime.Cache

如果是这样,最好的方法是什么?

【问题讨论】:

  • 一种讨厌的方法是将此对象的日期时间添加到不同的缓存对象中,然后使用 Date.Now() 减去该生命周期。

标签: c# asp.net caching


【解决方案1】:

我刚刚浏览了反射器中的 System.Web.Caching.Cache。似乎涉及到期日期的所有内容都标记为内部。我发现可以公开访问它的唯一地方是通过 Cache.Add 和 Cache.Insert 方法。

所以看起来你运气不好,除非你想进行反思,除非你真的需要那个日期,否则我不建议你这样做。

但如果你还是想这样做,那么这里有一些代码可以解决问题:

private DateTime GetCacheUtcExpiryDateTime(string cacheKey)
{
    object cacheEntry = Cache.GetType().GetMethod("Get", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Cache, new object[] { cacheKey, 1 });
    PropertyInfo utcExpiresProperty = cacheEntry.GetType().GetProperty("UtcExpires", BindingFlags.NonPublic | BindingFlags.Instance);
    DateTime utcExpiresValue = (DateTime)utcExpiresProperty.GetValue(cacheEntry, null);

    return utcExpiresValue;
}

Since .NET 4.5 HttpRuntime.Cache 的内部公共 getter 已替换为静态变体,因此您需要调用/获取静态变体:

object cacheEntry = Cache.GetType().GetMethod("Get").Invoke(null, new object[] { cacheKey, 1 });

【讨论】:

  • 你救了我的培根!这个代码!我永远不会想到这一点,因为我不熟悉 system.reflection!
  • 为什么不推荐使用这种方法?它会在查看时加载整个缓存对象吗?
  • 如果你能提供如何使用反射器的步骤,这对我真的很有帮助。我不能使用这个功能,因为它给出了一些错误。
  • 这在 .NET 4.7 中不起作用。内部 Get 方法已被删除。
  • 这似乎不再起作用,至少在 .net 4.5.2 中。现在有一个公共的 Get 方法,但它只返回缓存的值。
【解决方案2】:

正如 cmets 中的某人所建议的那样,接受的答案在 .NET 4.7 中不起作用

我在试图弄清楚需要进行哪些更改才能使其在 .NET 4.7 中工作时遇到了很多麻烦

这是我为使用 .NET 4.7 的人编写的代码

private DateTime GetCacheUtcExpiryDateTime(string cacheKey)
{
    var aspnetcachestoreprovider = System.Web.HttpRuntime.Cache.GetType().GetProperty("InternalCache", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(System.Web.HttpRuntime.Cache, null);
    var intenralcachestore = aspnetcachestoreprovider.GetType().GetField("_cacheInternal", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(aspnetcachestoreprovider);
    Type TEnumCacheGetOptions = System.Web.HttpRuntime.Cache.GetType().Assembly.GetTypes().Where(d => d.Name == "CacheGetOptions").FirstOrDefault();
    object cacheEntry = intenralcachestore.GetType().GetMethod("DoGet", BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Any, new[] { typeof(bool), typeof(string), TEnumCacheGetOptions }, null).Invoke(intenralcachestore, new Object[] { true, cacheKey, 1 }); ;
    PropertyInfo utcExpiresProperty = cacheEntry.GetType().GetProperty("UtcExpires", BindingFlags.NonPublic | BindingFlags.Instance);
    DateTime utcExpiresValue = (DateTime)utcExpiresProperty.GetValue(cacheEntry, null);

    return utcExpiresValue;
}

对于那些希望代码在多个不同环境(使用 .NET 4.5 的沙盒和使用 .NET 4.7 的生产环境)中运行的人来说,这里有一些补丁工作:

private DateTime GetCacheUtcExpiryDateTime(string cacheKey)
{
    MethodInfo GetCacheEntryMethod = null;
    Object CacheStore = null;
    bool GetterFound = true;

    GetCacheEntryMethod = System.Web.HttpRuntime.Cache.GetType().GetMethod("Get", BindingFlags.Instance | BindingFlags.NonPublic);
    if (GetCacheEntryMethod != null)
    {
        GetterFound = true;
        CacheStore = System.Web.HttpRuntime.Cache;
    }
    else
    {
        var aspnetcachestoreprovider = System.Web.HttpRuntime.Cache.GetType().GetProperty("InternalCache", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(System.Web.HttpRuntime.Cache, null);
        var intenralcachestore = aspnetcachestoreprovider.GetType().GetField("_cacheInternal", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(aspnetcachestoreprovider);
        Type TEnumCacheGetOptions = System.Web.HttpRuntime.Cache.GetType().Assembly.GetTypes().Where(d => d.Name == "CacheGetOptions").FirstOrDefault();
        GetCacheEntryMethod = intenralcachestore.GetType().GetMethod("DoGet", BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Any, new[] { typeof(bool), typeof(string), TEnumCacheGetOptions }, null);
        GetterFound = false;
        CacheStore = intenralcachestore;
    }

    dynamic cacheEntry;
    if (GetterFound)
        cacheEntry = GetCacheEntryMethod.Invoke(CacheStore, new Object[] { cacheKey, 1 });
    else
        cacheEntry = GetCacheEntryMethod.Invoke(CacheStore, new Object[] { true, cacheKey, 1 });

    PropertyInfo utcExpiresProperty = cacheEntry.GetType().GetProperty("UtcExpires", BindingFlags.NonPublic | BindingFlags.Instance);
    DateTime utcExpiresValue = (DateTime)utcExpiresProperty.GetValue(cacheEntry, null);

    return utcExpiresValue;
}

【讨论】:

  • 能否分享一下,如何获取CacheItemPriority?,和有效期一样。
【解决方案3】:

缓存本身不会过期。它可以有项目(过期)或根本没有任何项目。

【讨论】:

  • 你显然没有理解这个问题。
  • @Softlion:如果你有问题,你为什么不回答这个问题?
  • @Softlion:你愿意解释一下我的回复有什么问题吗?我不介意删除答案。
  • 问题是关于获取缓存中项目的到期日期。这个答案没有解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 2014-12-27
  • 2019-11-09
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
相关资源
最近更新 更多