2010-06-17 58 views
3

我創建了一個通用的包裝使用Cache對象:爲通用的System.Web.Caching.Cache包裝函數

public class Cache<T> where T : class 
{ 
    public Cache Cache {get;set;} 
    public CachedKeys Key {get;set;} 

    public Cache(Cache cache, CachedKeys key){ 
     Cache = cache; 
     Key = key; 
    } 

    public void AddToCache(T obj){ 
     Cache.Add(Key.ToString(), 
      obj, 
      null, 
      DateTime.Now.AddMinutes(5), 
      System.Web.Caching.Cache.NoSlidingExpiration, 
      System.Web.Caching.CacheItemPriority.Normal, 
      null);     
    } 

    public bool TryGetFromCache(out T cachedData) { 
     cachedData = Cache[Key.ToString()] as T; 
     return cachedData != null; 
    } 

    public void RemoveFromCache() { 
     Cache.Remove(Key.ToString()); } 
} 

的CachedKeys枚舉只是一個鍵的列表,可用於高速緩存數據。

麻煩的是,把它稱爲是相當convul​​uted:

var cache = new Cache<MyObject>(Page.Cache, CachedKeys.MyKey); 
MyObject myObject = null; 

if(!cache.TryGetFromCache(out myObject)){ 
    //get data... 
    cache.AddToCache(data); //add to cache 
    return data; 
} 

return myObject; 

我只保存我的每個高速緩存中的對象的一個​​實例。

因此,有沒有什麼辦法可以創建一個擴展方法來接受要緩存的對象類型並使用(通過Reflection)其Name作爲緩存鍵?

public static Cache<T> GetCache(this Cache cache, Type cacheType){ 
     Cache<cacheType> Cache = new Cache<cacheType>(cache, cacheType.Name); 
    } 

當然,有兩個錯誤的位置:

  • 擴展方法必須在非泛型靜態類
  • 類型或命名空間名稱「cacheType」被定義找不到

這顯然不是正確的方法,但我想我會展示我的工作。有人能指引我朝着正確的方向嗎?

+0

此方法線程安全嗎? – 2013-04-25 13:46:57

+0

不 - 你可以引入雙重檢查鎖定(即使不能保證)但懶惰填充緩存我建議任何鎖定會引入不必要的延遲。你可以在運行定時器的後臺線程上填充緩存(如果你對一個正在從線程池中取出的線程執行此操作感到滿意)。我傾向於不擔心 - 我不認爲緩存填充緩存需要線程安全。 – 2013-04-25 14:09:10

回答

5

我結束了使用通用的擴展方法:

public static class CacheExtensions 
{ 
    public static void Remove<T>(this Cache cache) where T : class 
    { 
     cache.Remove(typeof(T).Name); 
    } 

    public static void AddToCache<T>(this Cache cache, object item) where T : class 
    { 
     T outItem = null; 
     if (cache.TryGetItemFromCache<T>(out outItem)) 
      throw new ArgumentException("This item is already in the cache"); 

     cache.Insert(typeof(T).Name, 
       item, 
       null, 
       DateTime.Now.AddMinutes(5), 
       System.Web.Caching.Cache.NoSlidingExpiration, 
       System.Web.Caching.CacheItemPriority.Normal, 
       null); 
    } 

    public static bool TryGetItemFromCache<T>(this Cache cache, out T item) where T : class 
    { 
     item = cache.Get(typeof(T).Name) as T; 
     return item != null; 
    } 
} 

調用,如:

MyObject myObject = null; 
if(!Cache.TryGetItemFromCache(out myObject)){ 
    //get data 
    Cache.AddToCache<MyObject>(data); 
} 

and.. 

Cache.Remove<MyObject>(); 
1

如何:

public static Cache<T> GetCache<T>(this Cache cache) 
{ 
    return new Cache<T>(cache, typeof(T).Name); 
} 

當然,這必須在另一個類中定義。

+0

這基本上就是我在我的'Cache'構造函數中已經有的東西(除了使用'Name'屬性作爲一個鍵,這是一個後續思考的東西)。 – 2010-06-17 13:23:17

+0

但它做你想要的,不是嗎? – ErikHeemskerk 2010-06-17 13:32:34

+0

是的,我沒有想過簡單地製作一個泛型類而不是泛型類。我最後簡單地添加了通用擴展方法來實現現在的功能。 – 2010-06-17 14:04:50

0

我覺得下面的方法需要改變:

public static bool TryGetItemFromCache<T>(this Cache cache, out T item) where T : class 
    { 
     item = cache.Get(typeof(T).Name) as T; 
     return item != null; 
    } 

如果該項目是不在緩存中,您不想將項目放入緩存中供以後使用或稍後檢索。

謝謝,

+0

這將在調用代碼中處理。 'Cache'不知道數據來自何處。 – 2010-06-17 14:28:07