【发布时间】:2010-09-25 13:27:31
【问题描述】:
是否可以获得DateTime 对象的到期时间HttpRuntime.Cache?
如果是这样,最好的方法是什么?
【问题讨论】:
-
一种讨厌的方法是将此对象的日期时间添加到不同的缓存对象中,然后使用 Date.Now() 减去该生命周期。
是否可以获得DateTime 对象的到期时间HttpRuntime.Cache?
如果是这样,最好的方法是什么?
【问题讨论】:
我刚刚浏览了反射器中的 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 });
【讨论】:
正如 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;
}
【讨论】:
缓存本身不会过期。它可以有项目(过期)或根本没有任何项目。
【讨论】: