NET下三種緩存機制(Winform裏面的緩存使用 )

原文(http://www.cnblogs.com/wuhuacong/p/3526335.html)很是感謝伍華聰做者的分享!html

緩存在不少狀況下須要用到,合理利用緩存能夠一方面能夠提升程序的響應速度,同時能夠減小對特定資源訪問的壓力。本文主要針對本身在Winform方面的緩存使用作一個引導性的介紹,但願你們可以從中瞭解一些緩存的使用場景和使用方法。緩存是一箇中大型系統所必須考慮的問題。爲了不每次請求都去訪問後臺的資源(例如數據庫),咱們通常會考慮將一些更新不是很頻繁的,能夠重用的數據,經過必定的方式臨時地保存起來,後續的請求根據狀況能夠直接訪問這些保存起來的數據。這種機制就是所謂的緩存機制。數據庫

.NET 4.0的緩存功能主要由三部分組成:System.Runtime.Caching,System.Web.Caching.Cache和Output Cache。緩存

System.Runtime.Caching這是在.NET 4.0中新增的緩存框架,主要是使用MemoryCache對象,該對象存在於程序集System.Runtime.Caching.dll。框架

System.Web.Caching.Cache這個則是在.NET2.0開始就一直存在的緩存對象,通常主要用在Web中,固然也能夠用於Winform裏面,不過要引用System.Web.dll。ide

Output Cache則是Asp.NET裏面使用的,在ASP.NET 4.0以前的版本都是直接使用System.Web.Caching.Cache來緩存HTML片斷。在ASP.NET 4.0中對它進行了從新設計,提供了一個OutputCacheProvider供開發人員進行擴展,可是它默認狀況下,仍然使用System.Web.Caching.Cache來作作緩存。函數

一、自定義Hastable的緩存處理。

除了上面三種的緩存機制,通常咱們還能夠在靜態對象裏面經過HashTable或者Dictionary的方式進行自定義的緩存存儲和使用。優化

例如我在我本身所開發的程序裏面,都使用了工廠類來建立業務對象,因爲建立業務對象以及數據訪問層對象,是一個在界面或者中間層反覆調用的操做,所以須要把常常調用的對象把它存儲起來,下載調用的時候,直接從內存中取出來便可。以下面的BLLFactory類,就是一個基於泛型對象的業務類的建立操做,使用了基於Hashtable的靜態對象進行緩存處理。spa

 1 /// <summary>
 2 /// 對業務類進行構造的工廠類
 3 /// </summary>
 4 /// <typeparam name="T">業務對象類型</typeparam>
 5 public class BLLFactory<T> where T : class
 6 {
 7 private static Hashtable objCache = new Hashtable();
 8 private static object syncRoot = new Object();
 9 
10 /// <summary>
11 /// 建立或者從緩存中獲取對應業務類的實例
12 /// </summary>
13 public static T Instance
14 {
15 get
16 {
17 string CacheKey = typeof(T).FullName;
18 T bll = (T)objCache[CacheKey];  //從緩存讀取 
19 if (bll == null)
20 {
21 lock (syncRoot)
22 {
23 if (bll == null)
24 {
25 bll = Reflect<T>.Create(typeof(T).FullName, typeof(T).Assembly.GetName().Name); //反射建立,並緩存
26 objCache.Add(typeof(T).FullName, bll);
27 }
28 }
29 }
30 return bll;
31 }
32 }
33 }

二、使用.NET4.0的MemoryCache對象實現緩存設計

MemoryCache的使用網上介紹的很少,不過這個是.NET4.0新引入的緩存對象,估計主要是替換原來企業庫的緩存模塊,使得.NET的緩存能夠無處不在,而不用基於特定的Windows版本上使用。代理

首先咱們使用來建立一個基於MemoryCache的輔助類MemoryCacheHelper,方便調用進行緩存處理。

 1 /// <summary>
 2     /// 基於MemoryCache的緩存輔助類
 3     /// </summary>
 4     public static class MemoryCacheHelper
 5     {
 6         private static readonly Object _locker = new object();
 7      
 8         public static T GetCacheItem<T>(String key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
 9         {
10             if(String.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
11             if(cachePopulate == null) throw new ArgumentNullException("cachePopulate");
12             if(slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");
13      
14             if(MemoryCache.Default[key] == null)
15             {
16                 lock(_locker)
17                 {
18                     if(MemoryCache.Default[key] == null)
19                     {
20                         var item = new CacheItem(key, cachePopulate());
21                         var policy = CreatePolicy(slidingExpiration, absoluteExpiration);
22      
23                         MemoryCache.Default.Add(item, policy);
24                     }
25                 }
26             }
27      
28             return (T)MemoryCache.Default[key];
29         }
30      
31         private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
32         {
33             var policy = new CacheItemPolicy();
34      
35             if(absoluteExpiration.HasValue)
36             {
37                 policy.AbsoluteExpiration = absoluteExpiration.Value;
38             }
39             else if(slidingExpiration.HasValue)
40             {
41                 policy.SlidingExpiration = slidingExpiration.Value;
42             }
43      
44             policy.Priority = CacheItemPriority.Default;
45      
46             return policy;
47         }
48     }

這個輔助類只有一個public方法,就是GetCacheItem,使用的時候,須要指定key和獲取數據的處理代理,還有緩存的過時時間,是基於TimeSpan的仍是基於絕對時間的,選擇其一。

上面的輔助類,咱們在什麼狀況下會使用到呢?

假如在一個工做流模塊中用到了人員ID,而人員ID須要進行人員名稱的轉義,人員信息咱們通常知道放在權限系統模塊裏面,那麼若是在工做流裏面須要頻繁對人員ID進行轉義,那麼就須要方法調用權限系統的接口模塊,這樣處理就可使用緩存模塊進行優化處理的了。

 1 void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
 2         {
 3             if (e.Column.FieldName.Equals("ProcUser") || e.Column.FieldName.Equals("ProcUid") || e.Column.FieldName.Equals("UserId"))
 4             {
 5                 if (e.Value != null)
 6                 {
 7                     e.DisplayText = SecurityHelper.GetUserFullName(e.Value.ToString());
 8                 }
 9             }
10         }

其中的SecurityHelper.GetUserFullName是我對調用進行基於緩存的二次封裝,具體邏輯以下所示。

 1 /// <summary>
 2         /// 根據用戶的ID,獲取用戶的全名,並放到緩存裏面
 3         /// </summary>
 4         /// <param name="userId">用戶的ID</param>
 5         /// <returns></returns>
 6         public static string GetUserFullName(string userId)
 7         {            
 8             string key = "Security_UserFullName" + userId;
 9             string fullName = MemoryCacheHelper.GetCacheItem<string>(key,
10                 delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); },
11                 new TimeSpan(0, 30, 0));//30分鐘過時
12             return fullName;
13         }

MemoryCacheHelper的方法GetCacheItem裏面的Func<T>我使用了一個匿名函數用來獲取緩存的值。

1 delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); }

而調用BLLFactory<User>.Instance.GetFullNameByID則是從數據庫裏面獲取對應的數據了。

這樣在第一次或者緩存過時的時候,自動調用業務對象類的方法來獲取數據了。

最後,在界面上調用GetUserFullName的方法便可實現基於緩存方式的調用,程序第一次使用的,碰到指定的鍵沒有數據,就去數據庫裏面獲取,之後碰到該鍵,則直接獲取緩存的數據了。

下面圖形是程序具體的實現效果。

固然,以上兩種方式都還能夠經過AOP的注入方式實現代碼的簡化操做,不過因爲對AOP的引入,會涉及到更多的知識點,並且熟悉程序還不夠,因此依然採用較爲經常使用的方式來處理緩存的數據。

相關文章
相關標籤/搜索