詳解.NET 4.0可擴(kuò)展緩存框架
.NET Framework中,叫做System.Runtime.Caching,這不僅是個(gè)緩存庫(kù),還是個(gè)框架,可以在上面開(kāi)發(fā)自己的庫(kù)。ObjectCache定義了所有緩存都要實(shí)現(xiàn)的通用操作。與之搭配的是個(gè)內(nèi)存緩存實(shí)現(xiàn),叫做MemoryCache。這個(gè)緩存系統(tǒng)的結(jié)構(gòu)如下:
上圖大家可以看出來(lái)對(duì)應(yīng)那些產(chǎn)品了嗎?
下面我給大家介紹一個(gè)實(shí)現(xiàn)這樣一個(gè)架構(gòu)的代碼示例,代碼的核心就是ObjectCache:
定義一個(gè)抽象的Provider接口:
- public interface ICacheBuilder
- {
- ObjectCache GetInstance();
- string DefaultRegionName { get; }
- }
In-memory提供者的實(shí)現(xiàn)使用MemoryCache:
- public class MemoryCacheBuilder : ICacheBuilder
- {
- public MemoryCacheBuilder() { }
- public ObjectCache GetInstance()
- {
- return MemoryCache.Default;
- }
- public string DefaultRegionName
- {
- get { return null; }
- }
- }
分布式緩存提供者M(jìn)emcached:
- public class MemcachedCache : ObjectCache, ICacheBuilder
- {
- private long _lDefaultExpireTime = 3600; // default Expire Time
- private MemcachedClient _client = null;
- #region ICache Members
- public MemcachedCache()
- {
- this._client = MemcachedClientService.Instance.Client;
- }
- public override void Set(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
- {
- Enforce.NotNull(key, "key");
- CacheItem item = new CacheItem(key, value, regionName);
- CacheItemPolicy policy = new CacheItemPolicy();
- policy.AbsoluteExpiration = absoluteExpiration;
- Set(item, policy);
- }
- public override void Set(CacheItem item, CacheItemPolicy policy)
- {
- if (item == null || item.Value == null)
- return;
- item.Key = item.Key.ToLower();
- if (policy != null && policy.ChangeMonitors != null && policy.ChangeMonitors.Count > 0)
- throw new NotSupportedException("Change monitors are not supported");
- // max timeout in scaleout = 65535
- TimeSpan expire = (policy.AbsoluteExpiration.Equals(null)) ?
- policy.SlidingExpiration :
- (policy.AbsoluteExpiration - DateTimeOffset.Now);
- double timeout = expire.TotalMinutes;
- if (timeout > 65535)
- timeout = 65535;
- else if (timeout > 0 && timeout < 1)
- timeout = 1;
- this._client.Store(Enyim.Caching.Memcached.StoreMode.Set, item.Key.ToString(), item.Value);
- }
- public override object this[string key]
- {
- get
- {
- return Get(key);
- }
- set
- {
- Set(key, value, null);
- }
- }
- public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
- {
- CacheItem item = GetCacheItem(key, regionName);
- if (item == null)
- {
- Set(new CacheItem(key, value, regionName), policy);
- return value;
- }
- return item.Value;
- }
- public override CacheItem AddOrGetExisting(CacheItem value, CacheItemPolicy policy)
- {
- CacheItem item = GetCacheItem(value.Key, value.RegionName);
- if (item == null)
- {
- Set(value, policy);
- return value;
- }
- return item;
- }
- public override object AddOrGetExisting(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
- {
- CacheItem item = new CacheItem(key, value, regionName);
- CacheItemPolicy policy = new CacheItemPolicy();
- policy.AbsoluteExpiration = absoluteExpiration;
- return AddOrGetExisting(item, policy);
- }
- public override bool Contains(string key, string regionName = null)
- {
- return false;
- }
- public override CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
- {
- throw new System.NotImplementedException();
- }
- public override DefaultCacheCapabilities DefaultCacheCapabilities
- {
- get
- {
- return
- DefaultCacheCapabilities.OutOfProcessProvider |
- DefaultCacheCapabilities.AbsoluteExpirations |
- DefaultCacheCapabilities.SlidingExpirations |
- DefaultCacheCapabilities.CacheRegions;
- }
- }
- public override object Get(string key, string regionName = null)
- {
- key = key.ToLower();
- return this._client.Get(key);
- }
- public override CacheItem GetCacheItem(string key, string regionName = null)
- {
- object value = Get(key, regionName);
- if (value != null)
- return new CacheItem(key, value, regionName);
- return null;
- }
- public override long GetCount(string regionName = null)
- {
- return -1;
- }
- protected override System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string, object>> GetEnumerator()
- {
- throw new System.NotImplementedException();
- }
- public override System.Collections.Generic.IDictionary<string, object> GetValues(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
- {
- throw new System.NotImplementedException();
- }
- public override string Name
- {
- get { return "MemcachedProvider"; }
- }
- public override object Remove(string key, string regionName = null)
- {
- key = key.ToLower();
- return this._client.Remove(key);
- }
- public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null)
- {
- Set(new CacheItem(key, value, regionName), policy);
- }
- #endregion
- #region ICacheBuilder Members
- public ObjectCache GetInstance()
- {
- return this;
- }
- public string DefaultRegionName
- {
- get { throw new NotImplementedException(); }
- }
- #endregion
- }
分布式緩存提供者Windows Server AppFabric Caching:
- public class AppFabricCacheProvider : ObjectCache, ICacheBuilder
- {
- public static DataCache factory = null;
- public static object syncObj = new object();
- public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
- {
- CacheItem item = GetCacheItem(key, regionName);
- if (item == null)
- {
- Set(new CacheItem(key, value, regionName), policy);
- return value;
- }
- return item.Value;
- }
- public override CacheItem AddOrGetExisting(CacheItem value, CacheItemPolicy policy)
- {
- CacheItem item = GetCacheItem(value.Key, value.RegionName);
- if (item == null)
- {
- Set(value, policy);
- return value;
- }
- return item;
- }
- public override object AddOrGetExisting(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
- {
- CacheItem item = new CacheItem(key, value, regionName);
- CacheItemPolicy policy = new CacheItemPolicy();
- policy.AbsoluteExpiration = absoluteExpiration;
- return AddOrGetExisting(item, policy);
- }
- public override bool Contains(string key, string regionName = null)
- {
- return Get(key, regionName) != null;
- }
- public override CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
- {
- throw new NotImplementedException();
- }
- public override DefaultCacheCapabilities DefaultCacheCapabilities
- {
- get
- {
- return
- DefaultCacheCapabilities.OutOfProcessProvider |
- DefaultCacheCapabilities.AbsoluteExpirations |
- DefaultCacheCapabilities.SlidingExpirations |
- DefaultCacheCapabilities.CacheRegions;
- }
- }
- public override object Get(string key, string regionName = null)
- {
- key = key.ToLower();
- CreateRegionIfNeeded();
- return (regionName == null) ?
- CacheFactory.Get(key) :
- CacheFactory.Get(key, regionName);
- }
- public override CacheItem GetCacheItem(string key, string regionName = null)
- {
- object value = Get(key, regionName);
- if (value != null)
- return new CacheItem(key, value, regionName);
- return null;
- }
- public override long GetCount(string regionName = null)
- {
- if (string.IsNullOrEmpty(regionName))
- throw new NotSupportedException();
- return CacheFactory.GetObjectsInRegion(regionName).LongCount();
- }
- protected override System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string, object>> GetEnumerator()
- {
- throw new NotSupportedException();
- }
- public override System.Collections.Generic.IDictionary<string, object> GetValues(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
- {
- if (string.IsNullOrEmpty(regionName))
- throw new NotSupportedException();
- return CacheFactory.GetObjectsInRegion(regionName).ToDictionary(x => x.Key, x => x.Value);
- }
- public override string Name
- {
- get { return "AppFabric"; }
- }
- public override object Remove(string key, string regionName = null)
- {
- key = key.ToLower();
- CreateRegionIfNeeded();
- return (regionName == null) ?
- CacheFactory.Remove(key) :
- CacheFactory.Remove(key, regionName);
- }
- public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null)
- {
- Set(new CacheItem(key, value, regionName), policy);
- }
- public override void Set(CacheItem item, CacheItemPolicy policy)
- {
- if (item == null || item.Value == null)
- return;
- if (policy != null && policy.ChangeMonitors != null && policy.ChangeMonitors.Count > 0)
- throw new NotSupportedException("Change monitors are not supported");
- item.Key = item.Key.ToLower();
- CreateRegionIfNeeded();
- TimeSpan expire = (policy.AbsoluteExpiration.Equals(null)) ?
- policy.SlidingExpiration :
- (policy.AbsoluteExpiration - DateTimeOffset.Now);
- if (string.IsNullOrEmpty(item.RegionName))
- CacheFactory.Put(item.Key, item.Value, expire);
- else
- CacheFactory.Put(item.Key, item.Value, expire, item.RegionName);
- }
- private static DataCache CacheFactory
- {
- get
- {
- if (factory == null)
- {
- lock (syncObj)
- {
- if (factory == null)
- {
- DataCacheFactory cacheFactory = new DataCacheFactory();
- factory = cacheFactory.GetDefaultCache();
- }
- }
- }
- return factory;
- }
- }
- private void CreateRegionIfNeeded() 163: {
- try
- {
- CacheFactory.CreateRegion(DefaultRegionName);
- }
- catch (DataCacheException ex)
- {
- if (!ex.ErrorCode.Equals(DataCacheErrorCode.RegionAlreadyExists))
- throw ex;
- }
- }
- public override void Set(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
- {
- CacheItem item = new CacheItem(key, value, regionName);
- CacheItemPolicy policy = new CacheItemPolicy();
- policy.AbsoluteExpiration = absoluteExpiration;
- Set(item, policy);
- }
- public override object this[string key]
- {
- get
- {
- return Get(key, DefaultRegionName);
- }
- set
- {
- Set(key, value, null, DefaultRegionName);
- }
- }
- public ObjectCache GetInstance()
- {
- return this;
- }
- public string DefaultRegionName
- {
- get
- {
- string defaultRegion= FrameworkConfiguationManager.GetConfiguration().GetAppVariable("AppFabricCacheDefaultRegion");
- if (string.IsNullOrEmpty(defaultRegion))
- {
- defaultRegion = "Default";
- }
- return defaultRegion;
- }
- }
- }

代碼例子可以參看文章http://www.buraksenyurt.com/post/AspNet-40-Custom-Cache-Provider.aspx,在web.config中配置
- <caching>
- <outputCache defaultProvider="AspNetInternalProvider">
- <providers>
- <add name="DiskBasedCacheProvider" type="CustomCaching.DiskCacheProvider,CustomCaching"/>
- </providers>
- </outputCache>
- </caching>
在ASP.NET 4 的默認(rèn)輸出緩存策略中。所有的HTTP響應(yīng)、所呈現(xiàn)的頁(yè)面和控件緩存均使用上例所示的默認(rèn)輸出緩存提供程序(其中defaultProvider屬性值為AspNetInternalProvider)。通過(guò)為defaultProvider指定不同的提供程序。就可以更改web應(yīng)用程序的默認(rèn)輸出緩存提供程序。
另外,還可以針對(duì)每個(gè)用戶控件和各個(gè)請(qǐng)求選擇不同的輸出緩存提供程序。要為不同的Web用戶控件選擇不同的輸出緩存提供程序,最簡(jiǎn)便的方法是設(shè)置頁(yè)面或控件指令中新增加的providerName屬性,如下面的示例所示:
- <%@ OutputCache Duration="60" VaryByParam="None"
- providerName="DiskBasedCacheProvider" %>
若要為某個(gè)HTTP請(qǐng)求指定不同的輸出緩存提供程序,可以覆蓋Global.asax文件中新增加的GetOutputCacheProviderName方法,以編程的方式指定要用于特定請(qǐng)求的提供程序。
原文地址:.NET4.0的可擴(kuò)展緩存系統(tǒng)
鏈接:http://www.cnblogs.com/shanyou/archive/2010/07/01/1769547.html
【編輯推薦】