当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET清空缓存时遇到的问题简析

ASP.NET清空缓存时遇到的问题简析

2017年12月12日  | 移动技术网IT编程  | 我要评论

戒赌中心cngug,五月的节日,静坐冥想

在网站中要做一个清理缓存的功能(也就是在缓存为到期之前就强制缓存过期),程序中有的地方使用的httpruntime.cache来做的缓存,而和数据库交互部分则使用objectdatasource提供的缓存机制。清理httpruntime.cache的缓存很简单,只要

list<string> keys = new list<string>(); 
   // retrieve application cache enumerator 
idictionaryenumerator enumerator = httpruntime.cache.getenumerator(); 
   // copy all keys that currently exist in cache 
   while (enumerator.movenext()) 
   { 
    keys.add(enumerator.key.tostring()); 
   } 
   // delete every key from cache 
   for (int i = 0; i < keys.count; i++) 
   { 
    httpruntime.cache.remove(keys[i]); 
   } 

就可以了。

本以为objectdatasource等数据源的缓存也是保存在httpruntime.cache中,经过测试没想到竟然不是,因为执行上面的代码以后objectdatasource仍然是从缓存读取数据。

使用reflector反编译发现objectdatasource是使用httpruntime.cacheinternal来实现的缓存。cacheinternal是internal的,因此没法直接写代码调用,同时cacheinternal中也没提供清空缓存的方法,只能通过实验发现_caches._entries是保存缓存的hashtable,因此就用反射的方法调用cacheinternal,然后拿到_caches._entries,最后clear才算ok。

最终代码如下:

//httpruntime下的cacheinternal属性(internal的,内存中是cachemulti类型)是
objectdatasource等datasource保存缓存的管理器 
//因为cacheinternal、_caches、_entries等都是internal或者private的,
所以只能通过反射调用,而且可能会随着.net升级而失效 
 object cacheintern = commonhelper.getpropertyvalue(typeof(httpruntime), "cacheinternal") as ienumerable; 
 //_caches是cachemulti中保存多cachesingle的一个ienumerable字段。 
 ienumerable _caches = commonhelper.getfieldvalue(cacheintern, "_caches") as ienumerable; 
 foreach (object cachesingle in _caches) 
 { 
  clearcacheinternal(cachesingle); 
 } 
 
private static void clearcacheinternal(object cachesingle) 
{ 
 //_entries是cachesingle中保存缓存数据的一个private hashtable 
 hashtable _entries = commonhelper.getfieldvalue(cachesingle, "_entries") as hashtable; 
 _entries.clear(); 
} 
 
mary> 
/// 得到type类型的静态属性propertyname的值 
/// </summary> 
/// <param name="type"></param> 
/// <param name="propertyname"></param> 
/// <returns></returns> 
public static object getpropertyvalue(type type, string propertyname) 
{ 
 foreach (propertyinfo rinfo in type.getproperties
(bindingflags.nonpublic | bindingflags.static | bindingflags.public | bindingflags.instance)) 
 { 
  if (rinfo.name == propertyname) 
  { 
   return rinfo.getvalue(null, new object[0]); 
  } 
 } 
 throw new exception("无法找到属性:" + propertyname); 
} 
 
/// <summary> 
/// 得到object对象的propertyname属性的值 
/// </summary> 
/// <param name="obj"></param> 
/// <param name="propertyname"></param> 
/// <returns></returns> 
public static object getpropertyvalue(object obj, string propertyname) 
{ 
 type type = obj.gettype(); 
 foreach (propertyinfo rinfo in type.getproperties
(bindingflags.nonpublic | bindingflags.static | bindingflags.public | bindingflags.instance)) 
 { 
  if (rinfo.name == propertyname) 
  { 
   return rinfo.getvalue(obj, new object[0]); 
  } 
 } 
 throw new exception("无法找到属性:" + propertyname); 
} 
 
public static object getfieldvalue(object obj, string fieldname) 
{ 
 type type = obj.gettype(); 
 foreach (fieldinfo rinfo in type.getfields
(bindingflags.nonpublic | bindingflags.static | bindingflags.public | bindingflags.instance)) 
 { 
  if (rinfo.name == fieldname) 
  { 
   return rinfo.getvalue(obj); 
  } 
 } 
 throw new exception("无法找到字段:" + fieldname); 
} 

上面方法由于是通过crack的方法进行调用,可能有潜在的问题,因此仅供参考。

在google上搜索到另外一篇文章,主干是代码,代码的思路和我一样,贴过来也供参考。

private void clearoutputcache() 
{ 
 type ct = this.cache.gettype(); 
 fieldinfo cif = ct.getfield( "_cacheinternal", bindingflags.nonpublic | bindingflags.instance ); 
 type cmt = cache.gettype().assembly.gettype( "system.web.caching.cachemultiple" ); 
 type cachekeytype = cache.gettype().assembly.gettype( "system.web.caching.cachekey" ); 
 fieldinfo cachesfield = cmt.getfield( "_caches", bindingflags.nonpublic | bindingflags.instance ); 
 
 object cacheinternal = cif.getvalue( this.cache ); 
 object caches = cachesfield.getvalue( cacheinternal ); 
 
 type arraytype = typeof( array ); 
 methodinfo arraygetter = arraytype.getmethod( "getvalue", new type[] { typeof( int ) } ); 
 object cachesingle = arraygetter.invoke( caches, new object[] { 1 } ); 
 
 fieldinfo entriesfield = cachesingle.gettype().getfield( "_entries", bindingflags.instance | bindingflags.nonpublic ); 
 hashtable entries = (hashtable) entriesfield.getvalue( cachesingle ); 
 
 list<object> keys = new list<object>(); 
 foreach( object o in entries.keys ) 
 { 
  keys.add( o ); 
 } 
 
 methodinfo remove = cacheinternal.gettype().getmethod( "remove", bindingflags.nonpublic | bindingflags.instance, null, 
  new type[] { cachekeytype, typeof( cacheitemremovedreason ) }, null ); 
 foreach( object key in keys ) 
 { 
  remove.invoke( cacheinternal, new object[] { key, cacheitemremovedreason.removed } ); 
 } 
}

以上就是对asp.net清空缓存时遇到问题详细分析,为了让大家更好地解决此类问题,希望本文对大家的学习有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网