using JNPF.DependencyInjection; using Microsoft.Extensions.Caching.Memory; using System.Reflection; namespace JNPF.Common.Cache; /// /// 内存缓存. /// public class MemoryCache : ICache, ISingleton { private readonly IMemoryCache _memoryCache; /// /// 初始化一个类型的新实例. /// /// public MemoryCache(IMemoryCache memoryCache) { _memoryCache = memoryCache; } /// /// 用于在 key 存在时删除 key. /// /// 键. public long Del(params string[] key) { foreach (string? k in key) { _memoryCache.Remove(k); } return key.Length; } /// /// 用于在 key 存在时删除 key. /// /// 键. public Task DelAsync(params string[] key) { foreach (var k in key) { _memoryCache.Remove(k); } return Task.FromResult((long)key.Length); } /// /// 用于在 key 模板存在时删除. /// /// key模板. public async Task DelByPatternAsync(string pattern) { if (string.IsNullOrEmpty(pattern)) return default; // pattern = Regex.Replace(pattern, @"\{*.\}", "(.*)"); IEnumerable? keys = GetAllKeys().Where(k => k.StartsWith(pattern)); if (keys != null && keys.Any()) return await DelAsync(keys.ToArray()); return default; } /// /// 检查给定 key 是否存在. /// /// 键. public bool Exists(string key) { return _memoryCache.TryGetValue(key, out _); } /// /// 检查给定 key 是否存在. /// /// 键. public Task ExistsAsync(string key) { return Task.FromResult(_memoryCache.TryGetValue(key, out _)); } /// /// 获取指定 key 的增量值. /// /// 键. /// 增量. /// public long Incrby(string key, long incrBy) { throw new NotImplementedException(); } /// /// 获取指定 key 的增量值. /// /// 键. /// 增量. /// public Task IncrbyAsync(string key, long incrBy) { throw new NotImplementedException(); } /// /// 获取指定 key 的值. /// /// 键. public string Get(string key) { return _memoryCache.GetOrCreate(key, entry => { return entry.Value; })?.ToString(); } /// /// 获取指定 key 的值. /// /// byte[] 或其他类型. /// 键. public T Get(string key) { ICacheEntry entry = _memoryCache.Get(key); return entry == null ? default(T) : (T)(entry.Value); } /// /// 获取指定 key 的值. /// /// 键. public Task GetAsync(string key) { return Task.FromResult(Get(key)); } /// /// 获取指定 key 的值. /// /// byte[] 或其他类型. /// 键. public Task GetAsync(string key) { return Task.FromResult(Get(key)); } /// /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象. /// /// 键. /// 值. public bool Set(string key, object value) { var entry = _memoryCache.CreateEntry(key); entry.Value = value; _memoryCache.Set(key, entry); return true; } /// /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象. /// /// 键. /// 值. /// 有效期. public bool Set(string key, object value, TimeSpan expire) { var entry = _memoryCache.CreateEntry(key); entry.Value = value; _memoryCache.Set(key, entry, expire); return true; } /// /// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象. /// /// 键. /// 值. public Task SetAsync(string key, object value) { var entry = _memoryCache.CreateEntry(key); entry.Value = value; Set(key, entry); return Task.FromResult(true); } /// /// 保存. /// /// 键. /// 值. /// 过期时间. public Task SetAsync(string key, object value, TimeSpan expire) { var entry = _memoryCache.CreateEntry(key); entry.Value = value; Set(key, entry, expire); return Task.FromResult(true); } /// /// 获取所有key. /// public List GetAllKeys() { const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache); var cacheItems = entries.GetType().GetProperty("Keys").GetValue(entries) as ICollection; var keys = new List(); if (cacheItems == null) return keys; return cacheItems.Select(u => u.ToString()).ToList(); } /// /// 获取缓存过期时间0. /// /// /// public DateTime GetCacheOutTime(string key) { ICacheEntry? entry = _memoryCache.GetOrCreate(key, entry => { return entry; }); if (entry.AbsoluteExpiration == null) { return DateTime.Now; } DateTimeOffset dateTimeOffset = (DateTimeOffset)entry.AbsoluteExpiration; return dateTimeOffset.UtcDateTime; } /// /// 只有在 key 不存在时设置 key 的值. /// /// 键. /// 值. /// 有效期. public bool SetNx(string key, object value, TimeSpan expire) { throw new NotImplementedException(); } /// /// 只有在 key 不存在时设置 key 的值. /// /// 键. /// 值. public bool SetNx(string key, object value) { throw new NotImplementedException(); } }