新版網站
Asp.Net 4.0 新特性之 使用自定義OutputCache Provider
發布時間:2013/10/18   已被3508人閱讀    分享到:

在Asp.Net 4.0 的web.config文件中添加了關于緩存的配置節,如下所示:

<system.web> 
  <compilation debug="true" targetFramework="4.0" /> 
  <caching> 
    <outputCache defaultProvider="SmartOutputCache"> 
      <providers> 
        <add name="SmartOutputCache" type="OutputCacheTest.Caching.SmartOutputCacheProvider" 
             memoryCacheLimit="00:30:00"
             /> 
      </providers> 
    </outputCache> 
  </caching> 
</system.web>

我們可以在Web.config中配置自定義的OutputCacheProvider,并將自定義Provider指定為默認的Provider。

1.自定義OutputCacheProvider需要實現System.Web.Cacheing. OutputCacheProvider抽象類,網上有很多例子都用文件緩存做例子。這個例子太俗了,我寫了一個新的例子,在設置的緩存時間小于指定閥值時,緩存到HttpRuntime.Cache中,否則緩存到文件中,如下代碼:

 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Caching; 
using System.Xml.Serialization; 
using System.IO; 
using System.Runtime.Serialization.Formatters.Binary; 
  
namespace OutputCacheTest.Caching 
{ 
    /// <summary> 
    /// OutputCache精靈,如果緩存時間小于設置時間時則緩存到內存,否則緩存到文件 
    /// </summary> 
    public class SmartOutputCacheProvider : OutputCacheProvider 
    { 
        private const string KEY_PREFIX = "__outputCache_"; 
  
        /// <summary> 
        /// 初始化SmartOutputCacheProvider,讀取配置文件中配置的MemoryCacheLimit和FileCacheRoot的值 
        /// </summary> 
        /// <param name="name">provider名字</param> 
        /// <param name="config">配置</param> 
        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) 
        { 
            string memoryLimit = config["memoryCacheLimit"]; 
            if (memoryLimit == null) 
            { 
                MemoryCacheLimit = new TimeSpan(0, 30, 0); 
            } 
            else
            { 
                MemoryCacheLimit = TimeSpan.Parse(memoryLimit); 
            } 
  
            string fileCacheRoot = config["fileCa oot"]; 
            if (string.IsNullOrEmpty(fileCacheRoot)) 
            { 
                fileCacheRoot = AppDomain.CurrentDomain.BaseDirectory + "cache\\"; 
            } 
            this.FileCacheRoot = fileCacheRoot; 
            base.Initialize(name, config); 
        } 
  
        /// <summary> 
        /// 添加緩存 
        /// </summary> 
        /// <param name="key">緩存的鍵,key的值是有asp.net內部生成的</param> 
        /// <param name="entry">緩存的對象</param> 
        /// <param name="utcExpiry">過期時間</param> 
        /// <returns>返回緩存值</returns> 
        public override object Add(string key, object entry, DateTime utcExpiry) 
        { 
            Set(key, entry, utcExpiry); 
            return entry; 
        } 
  
        /// <summary> 
        /// 處理緩存鍵值,防止在文件緩存時出現文件路徑不允許的字符 
        /// </summary> 
        /// <param name="key">緩存鍵</param> 
        /// <returns>處理后的鍵</returns> 
        private string ProcessKey(string key) 
        { 
            return KEY_PREFIX + System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5"); 
        } 
  
        /// <summary> 
        /// 返回緩存文件的物理路徑 
        /// </summary> 
        /// <param name="processedKey">處理后的鍵</param> 
        /// <returns>物理路徑</returns> 
        private string GetFilePath(string processedKey) 
        { 
            return Path.Combine(FileCacheRoot, processedKey + ".data"); 
        } 
  
        /// <summary> 
        /// 獲得緩存值,如果在HttpRuntime.Cache中有則直接讀取內存中的值,否則從文件讀取 
        /// </summary> 
        /// <param name="key">緩存鍵</param> 
        /// <returns>緩存值</returns> 
        public override object Get(string key) 
        { 
            string processedKey = ProcessKey(key); 
  
            CacheDataWithExpiryTimeUtc result = HttpRuntime.Cache[processedKey] as CacheDataWithExpiryTimeUtc; 
            if (result == null) 
            { 
                string path = GetFilePath(processedKey); 
                if (!File.Exists(path)) 
                    return null; 
  
                using (FileStream file = File.OpenRead(path)) 
                { 
                    var formatter = new BinaryFormatter(); 
                    result = (CacheDataWithExpiryTimeUtc)formatter.Deserialize(file); 
                } 
            } 
  
            if (result == null || result.ExpiryTimeUtc <= DateTime.UtcNow) 
            { 
                Remove(key); 
                return null; 
            } 
            return result.Data; 
        } 
  
        /// <summary> 
        /// 根據鍵移除緩存 
        /// </summary> 
        /// <param name="key">緩存鍵</param> 
        public override void Remove(string key) 
        { 
            string processedKey = ProcessKey(key); 
            HttpRuntime.Cache.Remove(processedKey); 
            string path = GetFilePath(processedKey); 
            if (!File.Exists(path)) 
                File. (path); 
        } 
  
        /// <summary> 
        /// 設置緩存 
        /// </summary> 
        /// <param name="key">緩存鍵</param> 
        /// <param name="entry">緩存內容</param> 
        /// <param name="utcExpiry">過期時間</param> 
        public override void Set(string key, object entry, DateTime utcExpiry) 
        { 
            TimeSpan ts = utcExpiry - DateTime.UtcNow; 
            string processedKey = ProcessKey(key); 
  
            CacheDataWithExpiryTimeUtc cacheItem = new CacheDataWithExpiryTimeUtc 
            { 
                Data = entry, 
                ExpiryTimeUtc = utcExpiry 
            }; 
  
            if (ts <= MemoryCacheLimit) 
            { 
                HttpRuntime.Cache. (processedKey, cacheItem, null, utcExpiry.ToLocalTime(), TimeSpan.Zero); 
            } 
            else
            { 
                string cacheFilePath = GetFilePath(processedKey); 
                  
                using (var fs = new FileStream(cacheFilePath,FileMode.OpenOrCreate,FileAccess.ReadWrite)) 
                { 
                    var formatter = new BinaryFormatter(); 
                    formatter.Serialize(fs, cacheItem); 
                } 
            } 
        } 
  
        /// <summary> 
        /// 如果緩存設定的時間超過此值則緩存到文件中,否則在HttpRuntime.Cache中做緩存 
        /// </summary> 
        [XmlAttribute("memoryCacheLimit")] 
        public TimeSpan MemoryCacheLimit { get; set; } 
  
  
        /// <summary> 
        /// 文件緩存的根目錄,可以指定任何可訪問目錄 
        /// </summary> 
        [XmlAttribute("fileCacheRoot")] 
        public string FileCacheRoot { get; set; } 
    } 
  
    /// <summary> 
    /// 對緩存數據和緩存的過期時間的封裝 
    /// </summary> 
    [Serializable] 
    internal class CacheDataWithExpiryTimeUtc 
    { 
        public object Data { get; set; } 
  
        public DateTime ExpiryTimeUtc { get; set; } 
    } 
} 

2.如何使用自定義的OutputCacheProvider

    1)在配置文件中做配置,將自定義的實現作為默認輸出緩存支持,請看文章開始的配置
  2)在UserControl中指定使用Provider的名字,改名字在web.config中定義,例如

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="IamUserControl.ascx.cs" Inherits="OutputCacheTest.IamUserControl" %> 
<%@ OutputCache Duration="3000" ProviderName="AspNetInternalProvider" VaryByParam="None" %> 


  需要注意的是,只能在UserControl中指定Provider的名字,在Page的生明中是不允許的,在Page中默認情況會使用web.config中配置的defaultProvider,但是我們可以通過3)中介紹的方法給不同的頁面使用不同的OutputCacheProvider實現。

  3)在Global.asax文件中重寫GetOutputCacheProviderName(HttpContext context)方法,根據context返回不同的實現名字,如下例子

public override string GetOutputCacheProviderName(HttpContext context) 
{ 
    if (context.Request.Path.StartsWith("/default.aspx",StringComparison.CurrentCultureIgnoreCase)) 
    { 
        return "AspNetInternalProvider"; 
    } 
              
    return base.GetOutputCacheProviderName(context); 
} 
本文分享地址:http://www.adrhaerth.com/news/86.html上海網站建設公司朗晟網絡編輯,轉發請注明來源及版權歸屬。
上一篇:沒有了 【關閉】
下一篇:朗晟網絡公司新版官方網站正式上線
色聚阁