OutputCacheProvider OutputCache的一点点认识
在.net4.0后我们可以实现自己的outputcacheprovider来控制缓存的位置了,但是我发现很多人多outputcacheprovider的调用并不是很清楚。首先我们要知道缓存是在哪里注册的。答案是outputcachemodule
void ihttpmodule.init(httpapplication app)
{
if (runtimeconfig.getappconfig().outputcache.enableoutputcache)
{
app.resolverequestcache += new eventhandler(this.onenter);
app.updaterequestcache += new eventhandler(this.onleave);
}
}
(runtimeconfig.getappconfig().outputcache.enableoutputcache这句很明白检查我们的配置,看看你是否启用缓存。onenter是在处理前读取缓存数据,处理后设置缓存。
那么先让我们看看onenter的方法把,我把里面多数代码删除 只留主要的结果。
internal void onenter(object source, eventargs eventargs)
{
this._key = null;
string str;
this._key = str = this.createoutputcacheditemkey(context, null);
object obj2 = outputcache.get(str);
if (obj2 != null)
{
cachedvary cachedvary = obj2 as cachedvary;
if (cachedvary != null)
{
str = this.createoutputcacheditemkey(context, cachedvary);
obj2 = outputcache.get(str);}
application.completerequest();
return;
}
return;
}
}
这里有两次调用obj2 = outputcache.get(str),我们来分析一下吧,第一次取出来的数据被转化为cachedvary,这个东西就是保存我们outputcache中的那些属性配置的一个实例,所以outputcache不同的属性就会产生不同的cachedvary值,而第二次读取的obj2才是我们真正需要保存的东西,把它取到后做一系列的处理最后结束此次http请求。
如取值是取2次那么设置也一定是设置2次了。
internal void onleave(object source, eventargs eventargs)
{
cachedvary vary;
string str;
vary = new cachedvary(varybycontentencodings, varybyheaders, varybyparams, varybyallparams, currentsettings.varybycustom);
str = this.createoutputcacheditemkey(context, vary);
httprawresponse snapshot = response.getsnapshot();
string kernelcacheurl = response.setupkernelcaching(null);
guid cachedvaryid = (vary != null) ? vary.cachedvaryid : guid.empty;
cachedrawresponse rawresponse = new cachedrawresponse(snapshot, currentsettings, kernelcacheurl, cachedvaryid);
cachedependency dependencies = response.createcachedependencyforresponse();
outputcache.insertresponse(this._key, vary, str, rawresponse, dependencies, noabsoluteexpiration, noslidingexpiration);
}
}
在这里我们看到了cachedvary、cachedrawresponse的两个实例,在这里我们可以确定先前第二次调用obj2 = outputcache.get(str)的obj2应该是一个cachedrawresponse实例。而outputcache的insertresponse方法:
internal static void insertresponse(string cachedvarykey, cachedvary cachedvary, string rawresponsekey, cachedrawresponse rawresponse, cachedependency dependencies, datetime absexp, timespan slidingexp)
{
outputcacheprovider provider = getprovider(httpcontext.current);
provider.set(cachedvarykey, cachedvary, cache.noabsoluteexpiration);
provider.set(rawresponsekey, entry, absexp);
}
我相信大家看到这里就明白了,outputcache的保存和读取都是操作2个实例,一个是outputcache配置实例cachedvary ,另一个是真正的数据流cachedrawresponse 。
看到outputcache的insertresponse方法这里提到了outputcacheprovider provider = getprovider(httpcontext.current)而在outputcacheprovider 的get方法中也调用了这句
[csharp]
internal static object get(string key)
{
object obj2 = null;
outputcacheprovider provider = getprovider(httpcontext.current);
if (provider != null)
{
obj2 = provider.get(key);
outputcacheentry oce = obj2 as outputcacheentry;
if (oce != null)
{
if (hasdependencychanged(false, oce.dependencieskey, oce.dependencies, oce.kernelcacheurl, key, provider.name))
{
removefromprovider(key, provider.name);
return null;
}
obj2 = convert(oce);
}
}
if (obj2 == null)
{
obj2 = httpruntime.cacheinternal.get(key);
}
return obj2;
}
internal static object get(string key)
{
object obj2 = null;
outputcacheprovider provider = getprovider(httpcontext.current);
if (provider != null)
{
obj2 = provider.get(key);
outputcacheentry oce = obj2 as outputcacheentry;
if (oce != null)
{
if (hasdependencychanged(false, oce.dependencieskey, oce.dependencies, oce.kernelcacheurl, key, provider.name))
{
removefromprovider(key, provider.name);
return null;
}
obj2 = convert(oce);
}
}
if (obj2 == null)
{
obj2 = httpruntime.cacheinternal.get(key);
}
return obj2;
}
而outputcache的getprovider的方法干什么的我想我就不提了,相信大家都会明白。
所以要实现自定义的缓存,可以有两种方案分别是实现自己的outputcacheprovider和注册自己outputcachemodule
[csharp]
public class memorycacheprovider : outputcacheprovider
{
public override object add(string key, object entry, datetime utcexpiry)
{
return null;
}
public override object get(string key)
{
return null;
}
public override void set(string key, object entry, datetime utcexpiry)
{
}
public override void remove(string key)
{
}
}
ic class custoutputcachemodule : ihttpmodule
{
public void dispose()
{
}
public void init(httpapplication context)
{
context.resolverequestcache += new eventhandler(context_resolverequestcache);
context.updaterequestcache += new eventhandler(context_updaterequestcache);
}
void context_updaterequestcache(object sender, eventargs e)
{
}
void context_resolverequestcache(object sender, eventargs e)
{
}
}
public class memorycacheprovider : outputcacheprovider
{
public override object add(string key, object entry, datetime utcexpiry)
{
return null;
}
public override object get(string key)
{
return null;
}
public override void set(string key, object entry, datetime utcexpiry)
{
}
public override void remove(string key)
{
}
}
public class custoutputcachemodule : ihttpmodule
{
public void dispose()
{
}
public void init(httpapplication context)
{
context.resolverequestcache += new eventhandler(context_resolverequestcache);
context.updaterequestcache += new eventhandler(context_updaterequestcache);
}
void context_updaterequestcache(object sender, eventargs e)
{
}
void context_resolverequestcache(object sender, eventargs e)
{
}
}
相应的配置是
<caching>
<outputcache defaultprovider="channelinmemory">
<providers>
<add name="channelinmemory" type="mapp.memorycacheprovider,mvcapp" />
</providers>
</outputcache>
</caching>
<httpmodules>
<remove name="outputcache"/>
<add name="outputcache" type="mvcapp.custoutputcachemodule" />
</httpmodules>
分享到: