緩存這個東西可大可小,小到一個靜態的字段,大到將整個數據庫Cache起來。項目開發過程中緩存的應用到處可見,在這篇博文中筆者就來談談自己的項目中關於緩存實現。
最常見的緩存功能,如C#語言中的Dictionary對象,應該至少包含以下幾個功能:
- Init():緩存的初始化;
如:Dictionary<int, object> dic = new Dictioinary<int, object>(); - Add():增加緩存;
如:dic.Add(1, new object()); - Set():設置緩存 ;
這里的Set()和Add()是有一點區別的,Add()的時候發現已存在的緩存,則直接返回;而調用Set()的時候會檢查,如果不存在執行Add();如果存在,則替換(Remove first,then add)。如:dic[1] = new object(); - Reload();重新加載緩存,在某些情況想功能相當於Init;
如:dic=new Dictionary<int, object>(); - Remove():移除緩存;
如:dic.Remove(1),(注:執行Remove方法的時候,類似於Set,當key不存在的時候,不作任何處理); - Clear():清空緩存。
如:dic.clear();
如果你用過Dictionary對象的話,相信上面提到的方法對你都不會感到陌生,但是,僅僅一個Dictionary就能夠滿足我們的需要嗎?這里筆者來說說Dictionary的缺點:
- 一個Dictionary對象的實例是不夠用的;
並非所有的緩存的key都是int類型,所以你會在需要的地方不斷的定義Dictionary對象,管理起來到底有多難,你懂的。 - Dictionary的索引問題;
大家都知道,在進行Dictionary[key]操作的時候,首先要判斷是否存在。如果存在,則返回【或許你可以通過Dictionary.TryGetValue(...)方法來避開這一步檢查】;如果不存在,則要通過一些方式來獲取該對象,然后追加到緩存中去; - Dictionary的遍歷問題;
或許你會講,Dictionary是支持foreach遍歷的,好吧,這個我也承認;但是,你有沒有在有的時候,需要采用for的方式來遍歷Dictioanry對象實例呢?那個時候我想你肯定也糾結了一番。 - Dictionary的查找問題;
查找?不是可以通過key來索引嗎,還需要什么查找?好吧,這個我也承認;但是有些時候,我不僅僅只是需要通過鍵名key來查找啊,可能還需要通過dic.Find<TValue>(Predicate match), dic.FindAll<TValue>(Predicate match)等方式來查找,這個Dictionary有嗎?答案是:沒有。 - Dictionary的線程安全問題;
這點不多說,因為Dictionary不是線程安全的。 - Dictionary的與實際數據的同步問題;
一般來說,既然用到緩存,那么這些數據基本上是讀操作遠遠大於寫操作的,所以不可能為了那么一點點的寫操作,來額外加多一個定時器進行數據同步,如果是這樣的話,如果有100類數據需要進行緩存,那不是伴隨着100個定時。,難以想想,這是多么大的一個累贅啊。
請別上火,因為寫了這么多還在說理論;在寫我自己的緩存實現的時候,我首先要談談我這個緩存管理的應用場景,因為任何一項技術都是因為特定需求而產生的,脫離了實際需求的技術都是空談,說白了就是無用功。
在我的項目中,有很多的基礎對象,如果數據字典,枚舉,模塊,權限等數據庫對象,這些信息是在項目開發完成后基本上是不會再發生太大的改變的,而且這些數據的訪問平率是非常高的,如果每次訪問都需要一次數據庫連接的話,那對數據庫的壓力可想而知了。下面是ConcurrentDictionary.cs的代碼:
1
public
class ConcurrentDictionary<TKey, TData>
2 {
3 #region 私有字段
4
5 /// <summary>
6 /// 單一源數據(GetOneDataByOneKey)獲取器
7 /// </summary>
8 private Func<TKey, TData> _SourceDataGetter;
9 /// <summary>
10 /// 所有源數據獲取器
11 /// </summary>
12 private Func<List<TData>> _SourceAllDataGetter;
13 /// <summary>
14 /// 緩存存放字典對象
15 /// </summary>
16 private Dictionary<TKey, TData> _Dic;
17 /// <summary>
18 /// 緩存存放列表對象
19 /// </summary>
20 private List<TData> _List;
21 /// <summary>
22 /// 緩存鎖
23 /// </summary>
24 private object _Lock;
25
26 #endregion
27
28 #region 公共屬性
29
30 /// <summary>
31 /// 換成對象個數
32 /// </summary>
33 public int Count
34 {
35 get
36 {
37 return this._Dic.Count;
38 }
39 }
40
41 /// <summary>
42 /// 列表數據
43 /// </summary>
44 public List<TData> List
45 {
46 get
47 {
48 if ( this._List.Count < this._Dic.Count)
49 {
50 this._List.Clear();
51 foreach (KeyValuePair<TKey, TData> kvp in this._Dic)
52 {
53 this._List.Add(kvp.Value);
54 }
55 }
56 return this._List;
57 }
58 }
59
60 #endregion
61
62 #region 構造函數
63
64 /// <summary>
65 /// 默認構造
66 /// </summary>
67 public ConcurrentDictionary()
68 {
69 this._Dic = new Dictionary<TKey, TData>();
70 this._List = new List<TData>();
71 this._Lock = new object();
72 }
73
74 /// <summary>
75 /// 設置源數據獲取器
76 /// </summary>
77 /// <param name="sourceDataGetter"> 單一源數據(GetOneDataByOneKey)獲取器 </param>
78 public ConcurrentDictionary(Func<TKey, TData> sourceDataGetter)
79 {
80 if (sourceDataGetter == null) throw new ArgumentNullException( " sourceDataGetter ");
81 this._SourceDataGetter = sourceDataGetter;
82 this._Dic = new Dictionary<TKey, TData>();
83 this._List = new List<TData>();
84 this._Lock = new object();
85 }
86
87 /// <summary>
88 /// 設置源數據獲取器
89 /// </summary>
90 /// <param name="sourceAllDataGetter"> 所有源數據獲取器 </param>
91 public ConcurrentDictionary(Func<List<TData>> sourceAllDataGetter)
92 {
93 if (sourceAllDataGetter == null) throw new ArgumentNullException( " sourceAllDataGetter ");
94 this._SourceAllDataGetter = sourceAllDataGetter;
95 this._Dic = new Dictionary<TKey, TData>();
96 this._List = sourceAllDataGetter();
97 this._Lock = new object();
98 }
99
100 #endregion
101
102 #region 公共方法
103
104 /// <summary>
105 /// 獲取緩存數據
106 /// <para> 如果緩存中不存在,則通過SourceGetter獲取 </para>
107 /// <para> 如果通過SourceGetter獲取到null對象,則不添加到緩存 </para>
108 /// </summary>
109 /// <param name="key"> 鍵名 </param>
110 /// <param name="value"> 鍵值 </param>
111 /// <returns> 返回是否獲取成功 </returns>
112 public bool Get(TKey key, out TData value)
113 {
114 if (_Dic.TryGetValue(key, out value)) return true;
115 else
116 {
117 lock (_Lock)
118 {
119 if (_Dic.TryGetValue(key, out value)) return true;
120 if (_SourceDataGetter == null) return false;
121 TData tempData = _SourceDataGetter(key);
122 if (tempData != null)
123 {
124 _Dic.Add(key, tempData);
125 _List.Add(tempData);
126 value = tempData;
127 return true;
128 }
129 return false;
130 }
131 }
132 }
133
134 /// <summary>
135 /// 設置緩存數據
136 /// </summary>
137 /// <param name="key"> 鍵名 </param>
138 /// <param name="value"> 鍵值 </param>
139 /// <returns> 返回是否設置成功,如果鍵值已存在,則返回false </returns>
140 public bool Add(TKey key, TData value)
141 {
142 if (_Dic.ContainsKey(key)) return false;
143 else
144 {
145 lock (_Lock)
146 {
147 if (_Dic.ContainsKey(key)) return false;
148 else
149 {
150 _Dic.Add(key, value);
151 if (! this._List.Contains(value)) this._List.Add(value);
152 return true;
153 }
154 }
155 }
156 }
157
158 /// <summary>
159 /// 設置緩存數據
160 /// </summary>
161 /// <param name="key"> 鍵名 </param>
162 /// <param name="value"> 鍵值 </param>
163 /// <returns> 返回是否設置成功,如果鍵值已存在,則覆蓋 </returns>
164 public bool Set(TKey key, TData value)
165 {
166 if (_Dic.ContainsKey(key))
167 {
168 lock ( this._Lock)
169 {
170 // 移除老數據
171 TData oldData = _Dic[key];
172 _List.Remove(oldData);
173 // 增加新數據
174 _Dic[key] = value;
175 _List.Add(value);
176 return true;
177 }
178 }
179 else
180 {
181 lock (_Lock)
182 {
183 if (_Dic.ContainsKey(key))
184 {
185 // 移除老數據
186 TData oldData = _Dic[key];
187 _List.Remove(oldData);
188 // 增加新數據
189 _Dic[key] = value;
190 _List.Add(value);
191 return true;
192 }
193 else
194 {
195 _Dic.Add(key, value);
196 if (! this._List.Contains(value)) this._List.Add(value);
197 return true;
198 }
199 }
200 }
201 }
202
203 /// <summary>
204 /// 通過SourceDataGetter重新加載指定key的值
205 /// </summary>
206 /// <param name="key"> 鍵值 </param>
207 /// <returns></returns>
208 public bool Reload(TKey key)
209 {
210 if (_SourceDataGetter == null) return false;
211 TData tempData = _SourceDataGetter(key);
212 return this.Set(key, tempData);
213 }
214
215 /// <summary>
216 /// 通過SourceAllDataGetter重新加載所有緩存對象
217 /// </summary>
218 /// <returns></returns>
219 public bool ReloadAll()
220 {
221 if (_SourceAllDataGetter == null) return false;
222 lock ( this._Lock)
223 {
224 this._List = _SourceAllDataGetter();
225 }
226 return true;
227 }
228
229 /// <summary>
230 /// 移除鍵/值
231 /// </summary>
232 /// <param name="key"> 鍵名 </param>
233 /// <returns> 返回是否移除成功,如果不存在,則返回false </returns>
234 public bool Remove(TKey key)
235 {
236 TData tempData;
237 if ( this._Dic.TryGetValue(key, out tempData))
238 {
239 lock (_Lock)
240 {
241 _Dic.Remove(key);
242 _List.Remove(tempData);
243 return true;
244 }
245 }
246 return false;
247 }
248
249 /// <summary>
250 /// 清空緩存
251 /// </summary>
252 public void Clear()
253 {
254 lock (_Lock)
255 {
256 _Dic.Clear();
257 _List.Clear();
258 }
259 }
260
261 #endregion
2 {
3 #region 私有字段
4
5 /// <summary>
6 /// 單一源數據(GetOneDataByOneKey)獲取器
7 /// </summary>
8 private Func<TKey, TData> _SourceDataGetter;
9 /// <summary>
10 /// 所有源數據獲取器
11 /// </summary>
12 private Func<List<TData>> _SourceAllDataGetter;
13 /// <summary>
14 /// 緩存存放字典對象
15 /// </summary>
16 private Dictionary<TKey, TData> _Dic;
17 /// <summary>
18 /// 緩存存放列表對象
19 /// </summary>
20 private List<TData> _List;
21 /// <summary>
22 /// 緩存鎖
23 /// </summary>
24 private object _Lock;
25
26 #endregion
27
28 #region 公共屬性
29
30 /// <summary>
31 /// 換成對象個數
32 /// </summary>
33 public int Count
34 {
35 get
36 {
37 return this._Dic.Count;
38 }
39 }
40
41 /// <summary>
42 /// 列表數據
43 /// </summary>
44 public List<TData> List
45 {
46 get
47 {
48 if ( this._List.Count < this._Dic.Count)
49 {
50 this._List.Clear();
51 foreach (KeyValuePair<TKey, TData> kvp in this._Dic)
52 {
53 this._List.Add(kvp.Value);
54 }
55 }
56 return this._List;
57 }
58 }
59
60 #endregion
61
62 #region 構造函數
63
64 /// <summary>
65 /// 默認構造
66 /// </summary>
67 public ConcurrentDictionary()
68 {
69 this._Dic = new Dictionary<TKey, TData>();
70 this._List = new List<TData>();
71 this._Lock = new object();
72 }
73
74 /// <summary>
75 /// 設置源數據獲取器
76 /// </summary>
77 /// <param name="sourceDataGetter"> 單一源數據(GetOneDataByOneKey)獲取器 </param>
78 public ConcurrentDictionary(Func<TKey, TData> sourceDataGetter)
79 {
80 if (sourceDataGetter == null) throw new ArgumentNullException( " sourceDataGetter ");
81 this._SourceDataGetter = sourceDataGetter;
82 this._Dic = new Dictionary<TKey, TData>();
83 this._List = new List<TData>();
84 this._Lock = new object();
85 }
86
87 /// <summary>
88 /// 設置源數據獲取器
89 /// </summary>
90 /// <param name="sourceAllDataGetter"> 所有源數據獲取器 </param>
91 public ConcurrentDictionary(Func<List<TData>> sourceAllDataGetter)
92 {
93 if (sourceAllDataGetter == null) throw new ArgumentNullException( " sourceAllDataGetter ");
94 this._SourceAllDataGetter = sourceAllDataGetter;
95 this._Dic = new Dictionary<TKey, TData>();
96 this._List = sourceAllDataGetter();
97 this._Lock = new object();
98 }
99
100 #endregion
101
102 #region 公共方法
103
104 /// <summary>
105 /// 獲取緩存數據
106 /// <para> 如果緩存中不存在,則通過SourceGetter獲取 </para>
107 /// <para> 如果通過SourceGetter獲取到null對象,則不添加到緩存 </para>
108 /// </summary>
109 /// <param name="key"> 鍵名 </param>
110 /// <param name="value"> 鍵值 </param>
111 /// <returns> 返回是否獲取成功 </returns>
112 public bool Get(TKey key, out TData value)
113 {
114 if (_Dic.TryGetValue(key, out value)) return true;
115 else
116 {
117 lock (_Lock)
118 {
119 if (_Dic.TryGetValue(key, out value)) return true;
120 if (_SourceDataGetter == null) return false;
121 TData tempData = _SourceDataGetter(key);
122 if (tempData != null)
123 {
124 _Dic.Add(key, tempData);
125 _List.Add(tempData);
126 value = tempData;
127 return true;
128 }
129 return false;
130 }
131 }
132 }
133
134 /// <summary>
135 /// 設置緩存數據
136 /// </summary>
137 /// <param name="key"> 鍵名 </param>
138 /// <param name="value"> 鍵值 </param>
139 /// <returns> 返回是否設置成功,如果鍵值已存在,則返回false </returns>
140 public bool Add(TKey key, TData value)
141 {
142 if (_Dic.ContainsKey(key)) return false;
143 else
144 {
145 lock (_Lock)
146 {
147 if (_Dic.ContainsKey(key)) return false;
148 else
149 {
150 _Dic.Add(key, value);
151 if (! this._List.Contains(value)) this._List.Add(value);
152 return true;
153 }
154 }
155 }
156 }
157
158 /// <summary>
159 /// 設置緩存數據
160 /// </summary>
161 /// <param name="key"> 鍵名 </param>
162 /// <param name="value"> 鍵值 </param>
163 /// <returns> 返回是否設置成功,如果鍵值已存在,則覆蓋 </returns>
164 public bool Set(TKey key, TData value)
165 {
166 if (_Dic.ContainsKey(key))
167 {
168 lock ( this._Lock)
169 {
170 // 移除老數據
171 TData oldData = _Dic[key];
172 _List.Remove(oldData);
173 // 增加新數據
174 _Dic[key] = value;
175 _List.Add(value);
176 return true;
177 }
178 }
179 else
180 {
181 lock (_Lock)
182 {
183 if (_Dic.ContainsKey(key))
184 {
185 // 移除老數據
186 TData oldData = _Dic[key];
187 _List.Remove(oldData);
188 // 增加新數據
189 _Dic[key] = value;
190 _List.Add(value);
191 return true;
192 }
193 else
194 {
195 _Dic.Add(key, value);
196 if (! this._List.Contains(value)) this._List.Add(value);
197 return true;
198 }
199 }
200 }
201 }
202
203 /// <summary>
204 /// 通過SourceDataGetter重新加載指定key的值
205 /// </summary>
206 /// <param name="key"> 鍵值 </param>
207 /// <returns></returns>
208 public bool Reload(TKey key)
209 {
210 if (_SourceDataGetter == null) return false;
211 TData tempData = _SourceDataGetter(key);
212 return this.Set(key, tempData);
213 }
214
215 /// <summary>
216 /// 通過SourceAllDataGetter重新加載所有緩存對象
217 /// </summary>
218 /// <returns></returns>
219 public bool ReloadAll()
220 {
221 if (_SourceAllDataGetter == null) return false;
222 lock ( this._Lock)
223 {
224 this._List = _SourceAllDataGetter();
225 }
226 return true;
227 }
228
229 /// <summary>
230 /// 移除鍵/值
231 /// </summary>
232 /// <param name="key"> 鍵名 </param>
233 /// <returns> 返回是否移除成功,如果不存在,則返回false </returns>
234 public bool Remove(TKey key)
235 {
236 TData tempData;
237 if ( this._Dic.TryGetValue(key, out tempData))
238 {
239 lock (_Lock)
240 {
241 _Dic.Remove(key);
242 _List.Remove(tempData);
243 return true;
244 }
245 }
246 return false;
247 }
248
249 /// <summary>
250 /// 清空緩存
251 /// </summary>
252 public void Clear()
253 {
254 lock (_Lock)
255 {
256 _Dic.Clear();
257 _List.Clear();
258 }
259 }
260
261 #endregion
262 }
代碼中的注釋寫的相對比較詳細了,所以怎么用這里就不作任何多余的解釋了,如果只是上面這個類的話,還不足以滿足上面列出的Dictionary的缺點的第一點,所以筆者另外寫了一個緩存管理類,如下:
1
public
static
class CacheManager
2 {
3 #region 私有字段
4
5 /// <summary>
6 /// 緩存器
7 /// </summary>
8 static Dictionary< int, object> _Dic;
9
10 #endregion
11
12 #region 私有方法
13
14 static CacheManager()
15 {
16 _Dic = new Dictionary< int, object>();
17 }
18 /// <summary>
19 /// 獲取下一個緩存鍵名
20 /// </summary>
21 /// <returns></returns>
22 private static int _GetNextKey()
23 {
24 int key = Common.Random.Next( 1, 1000000);
25 while (_Dic.ContainsKey(key))
26 {
27 key = new Random().Next( 1, 1000000);
28 }
29 return key;
30 }
31 /// <summary>
32 /// 注冊字典
33 /// </summary>
34 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
35 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
36 /// <param name="dic"> 緩存 </param>
37 /// <returns> 緩存類別鍵名 </returns>
38 private static int _Register<TKey, TData>(ConcurrentDictionary<TKey, TData> dic)
39 {
40 int key = _GetNextKey();
41 _Dic.Add(key, dic);
42 return key;
43 }
44
45 #endregion
46
47 #region 公共方法
48
49 /// <summary>
50 /// 注冊緩存,並返回緩存鍵值
51 /// </summary>
52 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
53 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
54 /// <returns> 緩存類別鍵名 </returns>
55 public static int Register<TKey, TData>()
56 {
57 return _Register( new ConcurrentDictionary<TKey, TData>());
58 }
59
60 /// <summary>
61 /// 注冊緩存,並返回緩存鍵值
62 /// </summary>
63 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
64 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
65 /// <param name="sourceDataGetter"> 單一源數據(GetOneDataByOneKey)獲取器 </param>
66 /// <returns> 緩存類別鍵名 </returns>
67 public static int Register<TKey, TData>(Func<TKey, TData> sourceDataGetter)
68 {
69 return _Register( new ConcurrentDictionary<TKey, TData>(sourceDataGetter));
70 }
71
72 /// <summary>
73 /// 注冊緩存,並返回緩存鍵值
74 /// </summary>
75 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
76 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
77 /// <param name="sourceAllDataGetter"> 所有源數據獲取器 </param>
78 /// <returns> 緩存類別鍵名 </returns>
79 public static int Register<TKey, TData>(Func<List<TData>> sourceAllDataGetter)
80 {
81 return _Register( new ConcurrentDictionary<TKey, TData>(sourceAllDataGetter));
82 }
83
84 /// <summary>
85 /// 獲取緩存數據
86 /// <para> 如果緩存中不存在,則通過SourceGetter獲取 </para>
87 /// <para> 如果通過SourceGetter獲取到null對象,則不添加到緩存 </para>
88 /// </summary>
89 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
90 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
91 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
92 /// <param name="key"> 鍵名 </param>
93 /// <param name="value"> 鍵值 </param>
94 /// <returns> 返回是否獲取成功 </returns>
95 public static bool Get<TKey, TData>( int cacheTypeKey, TKey key, out TData value)
96 {
97 object obj;
98 if (_Dic.TryGetValue(cacheTypeKey, out obj))
99 {
100 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
101 return dic.Get(key, out value);
102 }
103 value = default(TData);
104 return false;
105 }
106
107 /// <summary>
108 /// 設置緩存數據
109 /// </summary>
110 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
111 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
112 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
113 /// <param name="key"> 鍵名 </param>
114 /// <param name="value"> 鍵值 </param>
115 /// <returns> 返回是否設置成功,如果鍵值已存在,則返回false </returns>
116 public static bool Add<TKey, TData>( int cacheTypeKey, TKey key, TData value)
117 {
118 object obj;
119 if (_Dic.TryGetValue(cacheTypeKey, out obj))
120 {
121 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
122 return dic.Add(key, value);
123 }
124 return false;
125 }
126
127 /// <summary>
128 /// 設置緩存數據
129 /// </summary>
130 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
131 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
132 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
133 /// <param name="key"> 鍵名 </param>
134 /// <param name="value"> 鍵值 </param>
135 /// <returns> 返回是否設置成功,如果鍵值已存在,則覆蓋 </returns>
136 public static bool Set<TKey, TData>( int cacheTypeKey, TKey key, TData value)
137 {
138 object obj;
139 if (_Dic.TryGetValue(cacheTypeKey, out obj))
140 {
141 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
142 return dic.Set(key, value);
143 }
144 return false;
145 }
146
147 /// <summary>
148 /// 通過SourceDataGetter重新加載指定key的值
149 /// </summary>
150 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
151 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
152 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
153 /// <param name="key"> 鍵值 </param>
154 /// <returns></returns>
155 public static bool Reload<TKey, TData>( int cacheTypeKey, TKey key)
156 {
157 object obj;
158 if (_Dic.TryGetValue(cacheTypeKey, out obj))
159 {
160 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
161 return dic.Reload(key);
162 }
163 return false;
164 }
165
166 /// <summary>
167 /// 通過SourceAllDataGetter重新加載指定類型緩存的所有緩存對象
168 /// </summary>
169 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
170 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
171 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
172 /// <returns></returns>
173 public static bool Reload<TKey, TData>( int cacheTypeKey)
174 {
175 object obj;
176 if (_Dic.TryGetValue(cacheTypeKey, out obj))
177 {
178 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
179 return dic.ReloadAll();
180 }
181 return false;
182 }
183
184 /// <summary>
185 /// 移除鍵/值
186 /// </summary>
187 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
188 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
189 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
190 /// <param name="key"> 鍵名 </param>
191 /// <returns> 返回是否移除成功,如果不存在,則返回false </returns>
192 public static bool Remove<TKey, TData>( int cacheTypeKey, TKey key)
193 {
194 object obj;
195 if (_Dic.TryGetValue(cacheTypeKey, out obj))
196 {
197 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
198 return dic.Remove(key);
199 }
200 return false;
201 }
202
203 /// <summary>
204 /// 清空緩存
205 /// </summary>
206 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
207 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
208 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
209 public static void Clear<TKey, TData>( int cacheTypeKey)
210 {
211 object obj;
212 if (_Dic.TryGetValue(cacheTypeKey, out obj))
213 {
214 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
215 dic.Clear();
216 }
217 }
218
219 /// <summary>
220 /// 清空所有緩存
221 /// </summary>
222 public static void ClearAll()
223 {
224 _Dic.Clear();
225 }
226
227 #endregion
2 {
3 #region 私有字段
4
5 /// <summary>
6 /// 緩存器
7 /// </summary>
8 static Dictionary< int, object> _Dic;
9
10 #endregion
11
12 #region 私有方法
13
14 static CacheManager()
15 {
16 _Dic = new Dictionary< int, object>();
17 }
18 /// <summary>
19 /// 獲取下一個緩存鍵名
20 /// </summary>
21 /// <returns></returns>
22 private static int _GetNextKey()
23 {
24 int key = Common.Random.Next( 1, 1000000);
25 while (_Dic.ContainsKey(key))
26 {
27 key = new Random().Next( 1, 1000000);
28 }
29 return key;
30 }
31 /// <summary>
32 /// 注冊字典
33 /// </summary>
34 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
35 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
36 /// <param name="dic"> 緩存 </param>
37 /// <returns> 緩存類別鍵名 </returns>
38 private static int _Register<TKey, TData>(ConcurrentDictionary<TKey, TData> dic)
39 {
40 int key = _GetNextKey();
41 _Dic.Add(key, dic);
42 return key;
43 }
44
45 #endregion
46
47 #region 公共方法
48
49 /// <summary>
50 /// 注冊緩存,並返回緩存鍵值
51 /// </summary>
52 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
53 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
54 /// <returns> 緩存類別鍵名 </returns>
55 public static int Register<TKey, TData>()
56 {
57 return _Register( new ConcurrentDictionary<TKey, TData>());
58 }
59
60 /// <summary>
61 /// 注冊緩存,並返回緩存鍵值
62 /// </summary>
63 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
64 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
65 /// <param name="sourceDataGetter"> 單一源數據(GetOneDataByOneKey)獲取器 </param>
66 /// <returns> 緩存類別鍵名 </returns>
67 public static int Register<TKey, TData>(Func<TKey, TData> sourceDataGetter)
68 {
69 return _Register( new ConcurrentDictionary<TKey, TData>(sourceDataGetter));
70 }
71
72 /// <summary>
73 /// 注冊緩存,並返回緩存鍵值
74 /// </summary>
75 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
76 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
77 /// <param name="sourceAllDataGetter"> 所有源數據獲取器 </param>
78 /// <returns> 緩存類別鍵名 </returns>
79 public static int Register<TKey, TData>(Func<List<TData>> sourceAllDataGetter)
80 {
81 return _Register( new ConcurrentDictionary<TKey, TData>(sourceAllDataGetter));
82 }
83
84 /// <summary>
85 /// 獲取緩存數據
86 /// <para> 如果緩存中不存在,則通過SourceGetter獲取 </para>
87 /// <para> 如果通過SourceGetter獲取到null對象,則不添加到緩存 </para>
88 /// </summary>
89 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
90 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
91 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
92 /// <param name="key"> 鍵名 </param>
93 /// <param name="value"> 鍵值 </param>
94 /// <returns> 返回是否獲取成功 </returns>
95 public static bool Get<TKey, TData>( int cacheTypeKey, TKey key, out TData value)
96 {
97 object obj;
98 if (_Dic.TryGetValue(cacheTypeKey, out obj))
99 {
100 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
101 return dic.Get(key, out value);
102 }
103 value = default(TData);
104 return false;
105 }
106
107 /// <summary>
108 /// 設置緩存數據
109 /// </summary>
110 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
111 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
112 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
113 /// <param name="key"> 鍵名 </param>
114 /// <param name="value"> 鍵值 </param>
115 /// <returns> 返回是否設置成功,如果鍵值已存在,則返回false </returns>
116 public static bool Add<TKey, TData>( int cacheTypeKey, TKey key, TData value)
117 {
118 object obj;
119 if (_Dic.TryGetValue(cacheTypeKey, out obj))
120 {
121 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
122 return dic.Add(key, value);
123 }
124 return false;
125 }
126
127 /// <summary>
128 /// 設置緩存數據
129 /// </summary>
130 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
131 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
132 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
133 /// <param name="key"> 鍵名 </param>
134 /// <param name="value"> 鍵值 </param>
135 /// <returns> 返回是否設置成功,如果鍵值已存在,則覆蓋 </returns>
136 public static bool Set<TKey, TData>( int cacheTypeKey, TKey key, TData value)
137 {
138 object obj;
139 if (_Dic.TryGetValue(cacheTypeKey, out obj))
140 {
141 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
142 return dic.Set(key, value);
143 }
144 return false;
145 }
146
147 /// <summary>
148 /// 通過SourceDataGetter重新加載指定key的值
149 /// </summary>
150 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
151 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
152 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
153 /// <param name="key"> 鍵值 </param>
154 /// <returns></returns>
155 public static bool Reload<TKey, TData>( int cacheTypeKey, TKey key)
156 {
157 object obj;
158 if (_Dic.TryGetValue(cacheTypeKey, out obj))
159 {
160 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
161 return dic.Reload(key);
162 }
163 return false;
164 }
165
166 /// <summary>
167 /// 通過SourceAllDataGetter重新加載指定類型緩存的所有緩存對象
168 /// </summary>
169 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
170 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
171 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
172 /// <returns></returns>
173 public static bool Reload<TKey, TData>( int cacheTypeKey)
174 {
175 object obj;
176 if (_Dic.TryGetValue(cacheTypeKey, out obj))
177 {
178 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
179 return dic.ReloadAll();
180 }
181 return false;
182 }
183
184 /// <summary>
185 /// 移除鍵/值
186 /// </summary>
187 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
188 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
189 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
190 /// <param name="key"> 鍵名 </param>
191 /// <returns> 返回是否移除成功,如果不存在,則返回false </returns>
192 public static bool Remove<TKey, TData>( int cacheTypeKey, TKey key)
193 {
194 object obj;
195 if (_Dic.TryGetValue(cacheTypeKey, out obj))
196 {
197 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
198 return dic.Remove(key);
199 }
200 return false;
201 }
202
203 /// <summary>
204 /// 清空緩存
205 /// </summary>
206 /// <typeparam name="TKey"> 緩存鍵名類型 </typeparam>
207 /// <typeparam name="TData"> 緩存鍵值類型 </typeparam>
208 /// <param name="cacheTypeKey"> 緩存類別鍵名 </param>
209 public static void Clear<TKey, TData>( int cacheTypeKey)
210 {
211 object obj;
212 if (_Dic.TryGetValue(cacheTypeKey, out obj))
213 {
214 ConcurrentDictionary<TKey, TData> dic = obj as ConcurrentDictionary<TKey, TData>;
215 dic.Clear();
216 }
217 }
218
219 /// <summary>
220 /// 清空所有緩存
221 /// </summary>
222 public static void ClearAll()
223 {
224 _Dic.Clear();
225 }
226
227 #endregion
228 }
以上兩個類 就是我的緩存管理的全部實現了,謝謝!
ASP.NET開發技術交流群: 67511751
另:本人想找一些志同道合的人,可以是跟我一起交流技術的,或者是給予鼓勵和支持的,非誠勿擾,謝謝!
QQ:1054930154
