2009-08-07 97 views
1

我正在尋找一種方法來獲得任何對象的通用本地緩存。這裏是代碼:類型安全的C#通用緩存

private static readonly Dictionary<Type,Dictionary<string,object>> _cache 
     = new Dictionary<Type, Dictionary<string, object>>(); 

    //The generic parameter allow null values to be cached 
    private static void AddToCache<T>(string key, T value) 
    { 
     if(!_cache.ContainsKey(typeof(T))) 
      _cache.Add(typeof(T),new Dictionary<string, object>()); 

     _cache[typeof (T)][key] = value; 
    } 

    private static T GetFromCache<T>(string key) 
    { 
     return (T)_cache[typeof (T)][key]; 
    } 

1-有沒有辦法不使用getfromcache方法?

2-有沒有一種方法可以確保第二個字典中的類型安全,即所有的對象都有相同的類型。 (這是由addToCache方法提供的,但我更喜歡設計中的類型控制)。對於例如,有_cache以下類型的

Dictionary<Type,Dictionary<string,typeof(type)>> 

THX

回答

12

試試這個:

static class Helper<T> 
{ 
     internal static readonly Dictionary<string, T> cache = new Dictionary<string, T>(); 
} 
private static void AddToCache<T>(string key, T value) 
{ 
    Helper<T>.cache[key] = value; 
} 
private static T GetFromCache<T>(string key) 
{ 
    return Helper<T>.cache[key]; 
} 
+1

+1更好,因爲每種類型現在都有自己的「名稱空間」。缺點是,最好不要從多個線程中使用它。 – 2009-08-07 13:55:02

+1

那麼,問題是關於類型安全性,而不是線程安全性。 公共靜態方法通常應該是線程安全的,所以需要在這裏添加鎖。 – Daniel 2009-08-07 14:02:22

+0

我真的很喜歡這個解決方案! – Toto 2009-08-07 14:07:33

3

爲什麼不乾脆把泛型參數和類聲明:

public class Cache<T> 
{ 
    private Dictionary<string, T> _cache = new Dictionary<string, T>(); 
    ... 

} 

它可以如果您願意,請保持靜態

0

如果在編譯時不知道所需的類型,將無法創建強類型的緩存。如果在運行時間之前您不知道所需的類型,那麼您的問題的答案是否定的,恐怕。

1

除非原始類型沒有裝盒,否則你不會獲得太多的收益。

private static readonly Dictionary<Type,Dictionary<string,object>> _cache 
    = new Dictionary<Type, IDictionary>(); 

//The generic parameter allow null values to be cached 
private static void AddToCache<T>(string key, T value) 
{ 
    // create a dictionary of the correct type 
    if(!_cache.ContainsKey(typeof(T))) 
     _cache.Add(typeof(T),new Dictionary<string, T>()); 

    _cache[typeof (T)][key] = value; 
} 

private static T GetFromCache<T>(string key) 
{ 
    // casting the dictionary instead of the value 
    Dictionary<string, T> typedDictionary = (Dictionary<string, T>)_cache[typeof (T)]; 
    return typedDictionary[key]; 
} 

當然,它需要更多未發現的處理。

+0

沒必要,請參閱Daniel的答案。將一個靜態字段放在一個泛型類中,它會自動成爲一個有效類型值的字典。 – 2009-08-07 14:01:15

+0

這是真的,但然後你有一個靜態字典,這並不總是適當的。 – 2009-08-07 14:11:40

0

應該可能在幾個鎖,也許幾個克隆折騰...但這應該做的。

class Program 
{ 
    static void Main(string[] args) 
    { 
     CacheObject<int>.Instance["hello"] = 5; 
     CacheObject<int>.Instance["hello2"] = 6; 
     CacheObject<string>.Instance["hello2"] = "hi"; 
     Console.WriteLine(CacheObject<string>.Instance["hello2"]); //returns hi 
    } 
} 

public class CacheObject<V> : CacheObject<string, V> { } 
public class CacheObject<K,V> 
{ 
    private static CacheObject<K, V> _instance = new CacheObject<K, V>(); 
    public static CacheObject<K, V> Instance { get { return _instance; } } 

    private Dictionary<K, V> _store = new Dictionary<K, V>(); 
    public T this[K index] 
    { 
     get { return _store.ContainsKey(index) ? _store[index] : default(V); } 
     set 
     { 
      if (_store.ContainsKey(index)) _store.Remove(index); 
      if (value != null) _store.Add(index, value); 
     } 
    } 
} 
0

我必須把它扔掉,這看起來並不像你應該做的。無論你使用的是依賴注入/反轉控制庫,Enterprise Library CacheManager這樣的工具,還是使用分佈式內存緩存程序(如Memcache或Microsoft Velocity),都可能更好地實現。