1 /*************************************************************************************
2 * CLR版本: 4.0.30319.34014
3 * 类 名 称: MemoryCacheClient
4 * 机器名称: WHL-PC
5 * 文 件 名: MemoryCacheClient
6 * 创建时间: 5/15/2014 2:12:30 PM
7 * 作 者:
8 * 说 明: 内存缓存策略
9 * 修改时间:
10 * 修 改 人:
11 *************************************************************************************/
12 using System;
13 using System.Collections.Concurrent;
14 using System.Collections.Generic;
15 using System.Linq;
16 using YCLib.Framework.LoggerProvider;
17
18 namespace YCLib.Framework.CacheProvider
19 {
20 internal class MemoryCacheClient : ICache,IDisposable
21 {
22 #region 私有变量
23
24 /// <summary>
25 /// 线程安全集合
26 /// </summary>
27 private readonly ConcurrentDictionary<string, CacheEntry> memory;
28
29 /// <summary>
30 /// 日志记录接口
31 /// </summary>
32 private static readonly ILog Log = LoggerFactory.GetLogger();
33
34
35 /// <summary>
36 /// 缓存数据对象
37 /// </summary>
38 private class CacheEntry
39 {
40 internal DateTime ExpiresAt { get; set; }
41 internal object Value { get; set; }
42
43 public CacheEntry(object value, DateTime expiresAt)
44 {
45 Value = value;
46 ExpiresAt = expiresAt;
47 }
48 }
49
50 private bool TryGetValue(string key, out CacheEntry entry)
51 {
52 return memory.TryGetValue(key, out entry);
53 }
54
55 //采用lazy实现线程安全的单例模式
56 private static readonly Lazy<MemoryCacheClient> lazy = new Lazy<MemoryCacheClient>(() => new MemoryCacheClient());
57
58
59
60 #endregion
61
62 /// <summary>
63 /// 对外公开对象
64 /// </summary>
65 public static MemoryCacheClient Instance { get { return lazy.Value; } }
66
67 private MemoryCacheClient()
68 {
69 memory = new ConcurrentDictionary<string, CacheEntry>();
70 }
71
72 public bool Remove(string key)
73 {
74 CacheEntry item;
75 return memory.TryRemove(key, out item);
76 }
77
78 public void RemoveAll(IEnumerable<string> keys)
79 {
80 foreach (var key in keys)
81 {
82 try
83 {
84 Remove(key);
85 }
86 catch (Exception ex)
87 {
88 Log.Error(new
89 {
90 F_AddUser = GetType().Name,
91 F_Message = ex.Message,
92 Exception = ex
93 }, ex);
94 }
95 }
96 }
97
98 public T Get<T>(string key)
99 {
100 try
101 {
102 CacheEntry cacheEntry;
103 if (memory.TryGetValue(key, out cacheEntry))
104 {
105 if (cacheEntry.ExpiresAt < DateTime.Now)
106 {
107 //如果缓存过期,则清除缓存项,并返回默认值
108 memory.TryRemove(key, out cacheEntry);
109 return default(T);
110 }
111 return (T)cacheEntry.Value;
112 }
113 return default(T);
114 }
115 catch (Exception ex)
116 {
117
118 Log.Error(new
119 {
120 F_AddUser = GetType().Name,
121 F_Message = ex.Message,
122 Exception = ex
123 }, ex);
124 return default(T);
125 }
126
127 }
128
129 public bool Add<T>(string key, T value)
130 {
131 try
132 {
133 return Add(key, value, DateTime.MaxValue);
134 }
135 catch (Exception)
136 {
137
138 return false;
139 }
140
141 }
142
143 public bool Set<T>(string key, T value)
144 {
145 return Set(key, value, DateTime.MaxValue);
146 }
147
148 public bool Replace<T>(string key, T value)
149 {
150 return Replace(key, value, DateTime.MaxValue);
151 }
152
153 public bool Add<T>(string key, T value, TimeSpan expiresIn)
154 {
155 return Add(key, value, DateTime.Now.Add(expiresIn));
156 }
157
158 public bool Set<T>(string key, T value, TimeSpan expiresIn)
159 {
160 return Set(key, value, DateTime.Now.Add(expiresIn));
161 }
162
163 public bool Replace<T>(string key, T value, TimeSpan expiresIn)
164 {
165 return Replace(key, value, DateTime.Now.Add(expiresIn));
166 }
167
168 public bool Add<T>(string key, T value, DateTime expiresAt)
169 {
170 try
171 {
172 CacheEntry entry;
173 //如果缓存中存在Key对应的值并且未过期,则Add失败
174 //如果已过期,则删除该项,并重新添加
175 if (TryGetValue(key, out entry))
176 {
177 if (entry.ExpiresAt < DateTime.Now)
178 {
179 return false;
180 }
181 memory.TryRemove(key, out entry);
182 }
183 Set(key, value, expiresAt);
184 return true;
185 }
186 catch (OutOfMemoryException)
187 {
188 return false;
189 }
190 }
191
192 public bool Set<T>(string key, T value, DateTime expiresAt)
193 {
194 var entry = new CacheEntry(value, expiresAt);
195 memory.AddOrUpdate(key, entry, (ekey, oldEntity) =>
196 {
197 oldEntity.ExpiresAt = entry.ExpiresAt;
198 oldEntity.Value = entry.Value;
199 return oldEntity;
200 });
201 return true;
202 }
203
204 public bool Replace<T>(string key, T value, DateTime expiresAt)
205 {
206 CacheEntry entry;
207 if (!TryGetValue(key, out entry))
208 {
209 return false;
210 }
211 entry.Value = value;
212 entry.ExpiresAt = expiresAt;
213 return true;
214 }
215
216 public void FlushAll()
217 {
218 memory.Clear();
219 }
220
221 public IDictionary<string, T> GetAll<T>(IEnumerable<string> keys)
222 {
223 var enumerable = keys as string[] ?? keys.ToArray();
224 if (keys == null || !enumerable.Any())
225 {
226 return null;
227 }
228 var valueMap = new Dictionary<string, T>(enumerable.Count());
229 foreach (var key in enumerable)
230 {
231 var value = Get<T>(key);
232 valueMap[key] = value;
233 }
234 return valueMap;
235 }
236
237 public void SetAll<T>(IDictionary<string, T> values)
238 {
239 foreach (var value in values)
240 {
241 Set(value.Key, value.Value);
242 }
243 }
244
245 public void Dispose()
246 {
247 memory.Clear();
248 }
249 }
250 }