欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

OutputCacheProvider OutputCache的一点点认识

程序员文章站 2022-05-26 16:07:20
在.net4.0后我们可以实现自己的outputcacheprovider来控制缓存的位置了,但是我发现很多人多outputcacheprovider的调用并不是很清楚。首先我们要知道缓存是在哪里注...

在.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>

 

分享到: