1 public interface ICacheManager
2 {
3 object GetFromCache(string key);
4 void AddToCache(string key, TimeSpan expireTimeSpan, RefreshObjectDelegate refreshObjectDelegate);
5 }
1 public class CacheManager : ICacheManager
2 {
3 private readonly ConcurrentDictionary<string, CacheObject> _cache = new ConcurrentDictionary<string, CacheObject>();
4 private static readonly object _lock = new object();
5 public void AddToCache(string key, TimeSpan expireTimeSpan, RefreshObjectDelegate refreshObjectDelegate)
6 {
7 if (!_cache.TryGetValue(key, out CacheObject o))
8 {
9 // check if the key exist or not; if no, then add it
10 CacheObject cacheObject = new CacheObject() { TimeOutSpan = expireTimeSpan, ExpireTime = DateTime.Now + expireTimeSpan, RefreshObjectDelegate = refreshObjectDelegate};
11 cacheObject.Value = cacheObject.RefreshObjectDelegate();
12 _cache[key] = cacheObject;
13 }
14 }
15
16 public object GetFromCache(string key)
17 {
18 if (!_cache.TryGetValue(key, out CacheObject o)) return null;
19 if (DateTime.Now < o.ExpireTime && o.Value != null)
20 {
21 return o.Value;
22 }
23 else
24 {
25 //async or mul-thread
26 lock(_lock)
27 {
28 if (DateTime.Now < o.ExpireTime && o.Value!=null)
29 {
30 return o.Value;
31 }
32 try
33 {
34 //get the data again, when it's expired
35 object newObject = o.RefreshObjectDelegate();
36 if ( newObject == null )
37 {
38 //if get data fails, return the old data and set the expiry time 1 min later
39 o.ExpireTime = DateTime.Now+ TimeSpan.FromMinutes(1);
40 return o.Value;
41 }
42 //if get data successfully, return the fresh data and set the expiry time TimeOutSpan later
43 o.Value = newObject;
44 o.ExpireTime = DateTime.Now + o.TimeOutSpan;
45 return newObject;
46 }
47 catch
48 {
49 //if get data fails, return the old data and set the expiry time 1 min later
50 o.ExpireTime = DateTime.Now + TimeSpan.FromMinutes(1);
51 return o.Value;
52 }
53 }
54 }
55 }
56 }
57
58 public delegate object RefreshObjectDelegate();
59
60 public class CacheObject
61 {
62 /// <summary>
63 /// Store the data
64 /// </summary>
65 public object Value { get; set; }
66 public TimeSpan TimeOutSpan { get; set; }
67 public DateTime ExpireTime { get; set; }
68
69 public RefreshObjectDelegate RefreshObjectDelegate;
70 }
1 public interface IStudent
2 {
3 List<string> GetAllStudents();
4 }
1 public class Student : IStudent
2 {
3 private readonly ICacheManager _cacheManager;
4 private const string CACHEKEY_STUDENT = "STUDENT";
5 public Student(ICacheManager cacheManager)
6 {
7 _cacheManager = cacheManager;
8 AddStudentToCache();
9 }
10
11 private void AddStudentToCache()
12 {
13 RefreshObjectDelegate refreshObjectDelegate = new RefreshObjectDelegate(GetAllStudentsFromDB);
14 //set expire time is 30 min
15 _cacheManager.AddToCache(CACHEKEY_STUDENT,TimeSpan.FromMinutes(30), refreshObjectDelegate);
16 }
17 private List<string> GetAllStudentsFromDB() {
18 //get data
19 List<string> list = new List<string>();
20 return list;
21 }
22 public List<string> GetAllStudents()
23 {
24 return (List<string>) _cacheManager.GetFromCache(CACHEKEY_STUDENT);
25 }
26 }