using Microsoft.Extensions.Caching.Memory; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; namespace UCFAR.AI.Common.Cache { public class MemoryCacheService : ICacheService { protected IMemoryCache Cache; public MemoryCacheService(IMemoryCache cache) { Cache = cache; } public static MemoryCacheService Default { get; private set; } static MemoryCacheService() { Default = new MemoryCacheService(new MemoryCache(new MemoryCacheOptions())); } /// <summary> /// 是否存在此缓存 /// </summary> /// <param name="key"></param> /// <returns></returns> public bool Exists(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); return Cache.TryGetValue<object>(key, out _); } /// <summary> /// 取得缓存数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(string key) where T : class { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); Cache.TryGetValue(key, out T v); return v; } /// <summary> /// 设置缓存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void SetCache(string key, object value) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); object v = null; if (Cache.TryGetValue(key, out v)) Cache.Remove(key); Cache.Set(key, value); } /// <summary> /// 设置缓存,绝对过期 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expirationMinute">间隔分钟</param> /// MemoryCacheService.Default.SetCache("test", "RedisCache works!", 30); public void SetCache(string key, object value, double expirationMinute) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); object v = null; if (Cache.TryGetValue(key, out v)) Cache.Remove(key); DateTime now = DateTime.Now; TimeSpan ts = now.AddMinutes(expirationMinute) - DateTime.Now; Cache.Set(key, value, ts); } /// <summary> /// 设置缓存,绝对过期 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expirationTime "> DateTimeOffset end time </ param> /// MemoryCacheService.Default.SetCache("test", "RedisCache works!", DateTimeOffset.Now.AddSeconds(30)); public void SetCache(string key, object value, DateTimeOffset expirationTime) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); if (Cache.TryGetValue(key, out _)) Cache.Remove(key); Cache.Set(key, value, expirationTime); } /// <summary> /// 设置缓存,相对过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="t"></param> /// MemoryCacheService.Default.SetCache("test", "MemoryCache works!",TimeSpan.FromSeconds(30)); public void SetSlidingCache(string key, object value, TimeSpan t) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); if (Cache.TryGetValue(key, out _)) Cache.Remove(key); Cache.Set(key, value, new MemoryCacheEntryOptions() { SlidingExpiration = t }); } /// <summary> /// 移除缓存 /// </summary> /// <param name="key"></param> public void RemoveCache(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); Cache.Remove(key); } /// <summary> /// 释放 /// </summary> public void Dispose() { Cache?.Dispose(); GC.SuppressFinalize(this); } #region 增加 /// <summary> /// </ summary> // add the cache /// <param name = "key" > Cache Key </ param> /// <param name = "value"> Cache the Value </ param> /// <param name = "expiresSliding"> long sliding expiration (if there expiration time in operation, places the current time point extended expiration time) </ param> /// <param name = "expiressAbsoulte"> absolute expiration duration </ param> /// <Returns> </ Returns> public BOOL SET (String Key, Object value, the TimeSpan expiresSliding, the TimeSpan expiressAbsoulte) { IF (Key == null) the throw new new ArgumentNullException The (NameOf (Key)); IF (value == null) the throw new new ArgumentNullException The (NameOf (value)); the Cache .Set (key, value, new MemoryCacheEntryOptions().SetSlidingExpiration(expiresSliding) .SetAbsoluteExpiration (expiressAbsoulte)); return the Exists (Key); } /// <Summary> /// Add cache /// </ Summary> /// <param name = "Key"> Cache Key </ param> / // <param name = "value" > cache the value </ param> /// <param name = "expiresIn"> cache duration </ param> /// <param name = "isSliding"> whether sliding expiration (if an operation within the expiration time, places the current time point extended expiration time) </ param> /// <Returns> </ Returns> public BOOL the Set (String Key, Object value, the TimeSpan expiresIn,bool isSliding = false) { if (key == null) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); Cache.Set(key, value, isSliding ? new MemoryCacheEntryOptions().SetSlidingExpiration(expiresIn) : new MemoryCacheEntryOptions().SetAbsoluteExpiration(expiresIn)); return Exists(key); } #region 删除缓存 /// <summary> /// 删除缓存 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public void Remove(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); Cache.Remove(key); } /// <summary> /// 批量删除缓存 /// </summary> /// <returns></returns> public void RemoveAll(IEnumerable<string> keys) { if (keys == null) throw new ArgumentNullException(nameof(keys)); keys.ToList().ForEach(item => Cache.Remove(item)); } #endregion #region 获取缓存 /// <summary> /// 获取缓存 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public T Get<T>(string key) where T : class { if (key == null) throw new ArgumentNullException(nameof(key)); return Cache.Get(key) as T; } /// <summary> /// 获取缓存 /// </summary> /// <param name="key">缓存Key</param> /// <returns></returns> public object Get(string key) { if (key == null) throw new ArgumentNullException(nameof(key)); return Cache.Get(key); } /// <summary> /// 获取缓存集合 /// </summary> /// <param name="keys">缓存Key集合</param> /// <returns></returns> public IDictionary<string, object> GetAll(IEnumerable<string> keys) { if (keys == null) throw new ArgumentNullException(nameof(keys)); var dict = new Dictionary<string, object>(); keys.ToList().ForEach(item => dict.Add(item, Cache.Get(item))); return dict; } #endregion /// <summary> /// 删除所有缓存 /// </summary> public void RemoveCacheAll() { var l = GetCacheKeys(); foreach (var s in l) { Remove(s); } } /// <Summary> /// Remove the matched cache /// </ Summary> /// <param name = "pattern"> </ param> /// <Returns> </ Returns> public void RemoveCacheRegex (String pattern) { the IList <String> L = SearchCacheRegex (pattern); the foreach (S in L var) { the Remove (S); } } /// <Summary> /// to search for a matching cache /// </ Summary> /// <param name = "pattern"> </ param> /// <Returns> </ Returns> public the IList <string> SearchCacheRegex(string pattern)string> SearchCacheRegex(string pattern) { var cacheKeys = GetCacheKeys(); var l = cacheKeys.Where(k => Regex.IsMatch(k, pattern)).ToList(); return l.AsReadOnly(); } /// <summary> /// 获取所有缓存键 /// </summary> /// <returns></returns> public List<string> GetCacheKeys() { const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; var entries = Cache.GetType().GetField("_entries", flags)?.GetValue(Cache); var cacheItems = entries as IDictionary; var keys = new List<string>(); if (cacheItems == null) return keys; foreach (DictionaryEntry CacheItem in cacheItems) { keys.Add (cacheItem.Key.ToString ()); } Return keys; } #Endregion } }