缓存这个东西可大可小,小到一个静态的字段,大到将整个数据库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