.NET Core MemoryCache 缓存键枚举实现
在 .NET Core 环境下,传统的 HttpRuntime.Cache 已被弃用,取而代之的是 Microsoft.Extensions.Caching.Memory 命名空间下的 MemoryCache 组件。虽然新版本的 API 与旧版功能类似,但它并未提供直接获取所有缓存键的方法。
为了实现这一功能,可以通过反射机制访问 MemoryCache 内部存储结构。以下代码展示了如何提取所有已存在的缓存键:
public List<string> GetAllKeys()
{
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
var entriesField = typeof(MemoryCache).GetField("_entries", bindingFlags);
var entriesValue = entriesField.GetValue(_memoryCache);
var cacheCollection = entriesValue as IDictionary;
var keyList = new List<string>();
if (cacheCollection != null)
{
foreach (DictionaryEntry entry in cacheCollection)
{
keyList.Add(entry.Key.ToString());
}
}
return keyList;
}
基于此技术,可以构建一个完整的缓存管理辅助类:
public class CacheManager
{
private readonly MemoryCache _memoryCache = new MemoryCache(new MemoryCacheOptions());
public bool ContainsKey(string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
return _memoryCache.TryGetValue(key, out _);
}
public bool SetValue(string key, object value, TimeSpan slidingExpiration, TimeSpan absoluteExpiration)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
if (value == null)
throw new ArgumentNullException(nameof(value));
_memoryCache.Set(key, value,
new MemoryCacheEntryOptions()
.SetSlidingExpiration(slidingExpiration)
.SetAbsoluteExpiration(absoluteExpiration));
return ContainsKey(key);
}
public bool SetValue(string key, object value, TimeSpan duration, bool useSliding = false)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
if (value == null)
throw new ArgumentNullException(nameof(value));
var options = new MemoryCacheEntryOptions();
if (useSliding)
options.SetSlidingExpiration(duration);
else
options.SetAbsoluteExpiration(duration);
_memoryCache.Set(key, value, options);
return ContainsKey(key);
}
public void DeleteKey(string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
_memoryCache.Remove(key);
}
public void DeleteMultipleKeys(IEnumerable<string> keys)
{
if (keys == null)
throw new ArgumentNullException(nameof(keys));
foreach (var key in keys)
_memoryCache.Remove(key);
}
public T GetValue<T>(string key) where T : class
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
return _memoryCache.Get(key) as T;
}
public object GetValue(string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
return _memoryCache.Get(key);
}
public IDictionary<string, object> GetMultipleValues(IEnumerable<string> keys)
{
if (keys == null)
throw new ArgumentNullException(nameof(keys));
var result = new Dictionary<string, object>();
foreach (var key in keys)
result[key] = _memoryCache.Get(key);
return result;
}
public void ClearAll()
{
var allKeys = GetAllKeys();
foreach (var key in allKeys)
DeleteKey(key);
}
public void DeleteByPattern(string pattern)
{
var matchedKeys = FindByPattern(pattern);
foreach (var key in matchedKeys)
DeleteKey(key);
}
public IList<string> FindByPattern(string pattern)
{
var allKeys = GetAllKeys();
return allKeys.Where(key => Regex.IsMatch(key, pattern)).ToList().AsReadOnly();
}
public List<string> GetAllKeys()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
var entriesField = typeof(MemoryCache).GetField("_entries", flags);
var entriesValue = entriesField.GetValue(_memoryCache);
var cacheItems = entriesValue as IDictionary;
var keys = new List<string>();
if (cacheItems != null)
{
foreach (DictionaryEntry item in cacheItems)
{
keys.Add(item.Key.ToString());
}
}
return keys;
}
}
该实现提供了完整的缓存操作接口,包括添加、查询、删除单个或多个缓存项,以及通过正则表达式模式匹配删除缓存等功能。