using System; using System.Collections.Generic; using System.Threading.Tasks; namespace System { /// <summary> /// 一個接口,表示緩存 /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TValue"></typeparam> public interface ICache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> { /// <summary> /// 獲取當前緩存的數量 /// </summary> int Count { get; } IEnumerable<TKey> Keys { get; } /// <summary> /// 是否包含鍵 /// </summary> bool ContainsKey(TKey key); /// <summary> /// 查詢緩存 /// </summary> /// <param name="key"></param> /// <param name="factory"></param> /// <returns></returns> TValue Get(TKey key, Func<TValue> factory); ///// <summary> ///// 查詢緩存 ///// </summary> ///// <param name="key"></param> ///// <returns></returns> //TValue Get(TKey key); /// <summary> /// 查詢緩存 /// </summary> /// <param name="key"></param> /// <param name="factory"></param> /// <returns></returns> Task<TValue> GetAsync(TKey key, Func<Task<TValue>> factory); ///// <summary> ///// 查詢緩存 ///// </summary> ///// <param name="key"></param> ///// <returns></returns> //Task<TValue> GetAsync(TKey key); /// <summary> /// 獲取數據,沒有返回默認值 /// </summary> /// <param name="index"></param> /// <returns></returns> TValue this[TKey key] { get; set; } /// <summary> /// 清空緩存 /// </summary> void Flush(); /// <summary> /// 更新緩存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> bool Update(TKey key, TValue value); /// <summary> /// 添加緩存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> bool Add(TKey key, TValue value); /// <summary> /// 添加或更新緩存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> void AddOrUpdate(TKey key, TValue value); /// <summary> /// 移除緩存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> bool Remove(TKey key); } }
using System.Collections; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Linq; namespace System { internal class Cache<TKey, TValue> : ICache<TKey, TValue> { Dictionary<TKey, TValue> _map = new Dictionary<TKey, TValue>(); ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); SemaphoreSlim _asyncLock; SemaphoreSlim AsyncLock { get { if (_asyncLock == null) { _asyncLock = new SemaphoreSlim(1, 1); } return _asyncLock; } } public int Count { get { return _map.Count; } } public IEnumerable<TKey> Keys { get { return _map.Keys; } } #region Get public TValue Get(TKey key, Func<TValue> factory) { // Check cache _lock.EnterReadLock(); TValue val; try { if (_map.TryGetValue(key, out val)) return val; } finally { _lock.ExitReadLock(); } // Cache it _lock.EnterWriteLock(); try { // Check again if (_map.TryGetValue(key, out val)) return val; // Create it val = factory(); // Store it _map.Add(key, val); // Done return val; } finally { _lock.ExitWriteLock(); } } //public TValue Get(TKey key) //{ // // Check cache // _lock.EnterReadLock(); // TValue val; // try // { // _map.TryGetValue(key, out val); // return val; // } // finally // { // _lock.ExitReadLock(); // } //} public async Task<TValue> GetAsync(TKey key, Func<Task<TValue>> factory) { // Check cache //_lock.EnterReadLock(); await AsyncLock.WaitAsync(-1); TValue val; try { if (_map.TryGetValue(key, out val)) return val; } finally { AsyncLock.Release(); //_lock.ExitReadLock(); } // Cache it //_lock.EnterWriteLock(); await AsyncLock.WaitAsync(-1); try { // Check again if (_map.TryGetValue(key, out val)) return val; // Create it val = await factory(); // Store it _map.Add(key, val); // Done return val; } finally { //_lock.ExitWriteLock(); AsyncLock.Release(); } } //public async Task<TValue> GetAsync(TKey key) //{ // // Check cache // //_lock.EnterReadLock(); // await AsyncLock.WaitAsync(-1); // TValue val; // try // { // _map.TryGetValue(key, out val); // return val; // } // finally // { // AsyncLock.Release(); // //_lock.ExitReadLock(); // } //} #endregion /// <summary> /// 獲取數據,沒有返回默認值 /// </summary> /// <param name="index"></param> /// <returns></returns> public TValue this[TKey key] { get { _lock.EnterReadLock(); TValue val; try { if (_map.TryGetValue(key, out val)) return val; } finally { _lock.ExitReadLock(); } return default(TValue); } set { AddOrUpdate(key, value); } } public bool Update(TKey key, TValue value) { _lock.EnterReadLock(); TValue val; try { if (!_map.TryGetValue(key, out val)) return false; //val = value; _map[key] = value; return true; } finally { _lock.ExitReadLock(); } } public bool Add(TKey key, TValue value) { _lock.EnterReadLock(); TValue val; try { if (_map.TryGetValue(key, out val)) return false; _map.Add(key, value); return true; } finally { _lock.ExitReadLock(); } } public void AddOrUpdate(TKey key, TValue value) { _lock.EnterReadLock(); TValue val; try { if (_map.TryGetValue(key, out val)) // val = value; _map[key] = value; else _map.Add(key, value); } finally { _lock.ExitReadLock(); } } public bool Remove(TKey key) { _lock.EnterReadLock(); try { return _map.Remove(key); } finally { _lock.ExitReadLock(); } } public void Flush() { // Cache it _lock.EnterWriteLock(); try { _map.Clear(); } finally { _lock.ExitWriteLock(); } } public bool ContainsKey(TKey key) { _lock.EnterReadLock(); TValue val; try { if (_map.TryGetValue(key, out val)) return true; return false; } finally { _lock.ExitReadLock(); } } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _map.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_map).GetEnumerator(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace System { /// <summary> /// 緩存工廠 /// </summary> public static class CacheFactory { internal static readonly List<Action> _actions; internal static readonly Timer _timer; static CacheFactory() { _expireTime = 60; _actions = new List<Action>(); _timer = new Timer(o => { var actions = o as IEnumerable<Action>; object lockObj = new object(); lock (lockObj) { foreach (var item in actions) { try { item(); } catch { } } } }, _actions, Timeout.Infinite, Timeout.Infinite); int time = 1000 * 60 * _expireTime; _timer.Change(time, time); } static int _expireTime; /// <summary> /// 獲取或設置過期時間 /// </summary> public static int ExpireTime { get { return _expireTime; } set { _expireTime = value; int time = 1000 * 60 * _expireTime; _timer.Change(time, time); } } /// <summary> /// 創建一個緩存 /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TValue"></typeparam> /// <returns></returns> public static ICache<TKey, TValue> CreateCache<TKey, TValue>() { return new Cache<TKey, TValue>(); //return ActivatorFactory.CreateInstance<ICache<TKey, TValue>>(); } /// <summary> /// 創建一個過期緩存 /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TValue"></typeparam> /// <returns></returns> public static IExpireCache<TKey, TValue> CreateExpireCache<TKey, TValue>() { return new ExpireCache<TKey, TValue>(); //return ActivatorFactory.CreateInstance<IExpireCache<TKey, TValue>>(); } /// <summary> /// 創建一個過期緩存 /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TValue"></typeparam> /// <returns></returns> public static IExpireCache<TValue> CreateExpireCache<TValue>() { return new ExpireCache<TValue>(); //return ActivatorFactory.CreateInstance<IExpireCache<TValue>>(); } } }