2012-09-13 19 views
1

看起來好像一旦將緩存性設置爲Response.CacheNoCache,則無法再次更改它。這是一個簡單但完整的問題說明:將其設置爲NoCache後更改Response.Cache._cacheability

protected void Page_Load(object sender, EventArgs e) 
{ 
    FieldInfo fi = typeof(HttpCachePolicy).GetField(
     "_cacheability", 
     BindingFlags.NonPublic | BindingFlags.Instance); 

    // Default value = 6 
    HttpCacheability first = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can change it to Public 
    Response.Cache.SetCacheability(HttpCacheability.Public); 
    HttpCacheability second = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can change it to Private 
    Response.Cache.SetCacheability(HttpCacheability.Private); 
    HttpCacheability third = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can change it to NoCache 
    Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    HttpCacheability fourth = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can't go back to Private! Stuck on NoCache 
    Response.Cache.SetCacheability(HttpCacheability.Private); 
    HttpCacheability fifth = (HttpCacheability)fi.GetValue(Response.Cache); 
} 

我錯過了什麼嗎?有沒有辦法做到這一點?

編輯:當然,它的工作原理,如果我與反思設置它,但我擔心,還有別的情況發生,當你設置爲HttpCacheability.NoCache如果我去幕後,我會想念..和希望無論如何都要以官方支持的方式來完成。

編輯2:同樣的事情似乎發生在Private;你只能限制更多嗎?

protected void Page_Load(object sender, EventArgs e) 
{ 
    FieldInfo fi = typeof(HttpCachePolicy).GetField(
     "_cacheability", 
     BindingFlags.NonPublic | BindingFlags.Instance); 

    // Default value = 6 
    HttpCacheability first = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can change it to Private 
    Response.Cache.SetCacheability(HttpCacheability.Private); 
    HttpCacheability second = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can't change to Public! Stuck on Private 
    Response.Cache.SetCacheability(HttpCacheability.Public); 
    HttpCacheability third = (HttpCacheability)fi.GetValue(Response.Cache); 

    // Can change to NoCache - Can only go more restrictive? 
    Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    HttpCacheability fourth = (HttpCacheability)fi.GetValue(Response.Cache); 
} 

回答

1

裂了開來反射並看了看裏面HttpCachePolicy

public void SetCacheability(HttpCacheability cacheability) 
{ 
    if ((cacheability < HttpCacheability.NoCache) || (HttpCacheability.ServerAndPrivate < cacheability)) 
    { 
     throw new ArgumentOutOfRangeException("cacheability"); 
    } 
    if (s_cacheabilityValues[(int) cacheability] < s_cacheabilityValues[(int) this._cacheability]) 
    { 
     this.Dirtied(); 
     this._cacheability = cacheability; 
    } 
} 

s_cacheabilityValues靜態構造函數中設置:

s_cacheabilityValues = new int[] { -1, 0, 2, 1, 4, 3, 100 }; 

Dirtied()被調用,但它似乎只是設置一些標誌:

private void Dirtied() 
{ 
    this._isModified = true; 
    this._useCachedHeaders = false; 
} 

它確實看起來有改變值的規則,但看起來沒有太大的影響。因此,使用反射來改變可能是安全的。

fi.SetValue(Response.Cache, HttpCacheability.Private); 
+0

現在回想起來這一點,可能要在設定'_useCachedHeaders'爲假同時,或者只是使用反射調用'Dirtied()'。 – zimdanen

0

事實上,似乎反射是唯一安全的方式。展望代碼越深,則需要從響應的Cache屬性提取類型爲HttpCachePolicy的對象,你可以在下面看到它:

public class HttpCachePolicyWrapper : HttpCachePolicyBase 
{ 
    private HttpCachePolicy _httpCachePolicy; 
    .... 
} 

要做到這一點,只需使用反射來設置的值正確的對象從Response.Cache對象像下面的代碼:

FieldInfo fi = typeof(HttpCachePolicy).GetField("_cacheability", BindingFlags.NonPublic | BindingFlags.Instance); 
var objectToChange = (HttpCachePolicy)context.Response.Cache.GetType().GetField("_httpCachePolicy", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(context.Response.Cache); 
fi.SetValue(objectToChange, HttpCacheability.Public); 

這只是增加了更多的conrete步驟將zimdanen的回答

相關問題