.NET 8中如何获取IMemoryCache缓存键的过期时间?
在.NET 8中获取MemoryCache缓存键的过期时间
IMemoryCache本身没有公开API直接获取缓存项的过期时间,因此需要在设置缓存时主动记录过期信息,以下是两种可行的实现方案:
方案一:将缓存值与过期时间封装为自定义对象
创建通用封装类,把缓存值和过期时间绑定后存入缓存,后续获取时就能同时拿到过期信息。
步骤1:定义缓存项封装类
public class CacheItem<T> { // 缓存的实际业务值 public T Value { get; set; } // 绝对过期时间(UTC时区) public DateTime? AbsoluteExpiration { get; set; } }
步骤2:修改Set方法存储封装对象
public bool Set<T>(string key, T value, TimeSpan? expiration = null) { var cacheItem = new CacheItem<T> { Value = value, AbsoluteExpiration = expiration.HasValue ? DateTime.UtcNow.Add(expiration.Value) : null }; var options = new MemoryCacheEntryOptions(); if (expiration.HasValue) { options.SetAbsoluteExpiration(expiration.Value); } _cache.Set(key, cacheItem, options); return true; }
步骤3:添加获取过期时间的方法
// 获取指定键的过期时间 public DateTime? GetExpiration(string key) { if (_cache.TryGetValue(key, out CacheItem<object> cacheItem)) { return cacheItem.AbsoluteExpiration; } return null; } // 同时获取缓存值和过期时间的泛型方法 public (T? Value, DateTime? Expiration) GetWithExpiration<T>(string key) { if (_cache.TryGetValue(key, out CacheItem<T> cacheItem)) { return (cacheItem.Value, cacheItem.AbsoluteExpiration); } return (default, null); }
方案二:维护独立字典记录过期时间
在MemoryCacheService中维护一个并发字典,同步记录每个缓存键的过期时间,并通过缓存项的移除回调自动清理字典中的无效记录。
步骤1:添加并发字典字段
private readonly ConcurrentDictionary<string, DateTime?> _cacheExpirations = new();
步骤2:修改Set方法同步记录过期时间
public bool Set<T>(string key, T value, TimeSpan? expiration = null) { var options = new MemoryCacheEntryOptions(); DateTime? absoluteExpiration = null; if (expiration.HasValue) { absoluteExpiration = DateTime.UtcNow.Add(expiration.Value); options.SetAbsoluteExpiration(expiration.Value); } // 注册回调:缓存项被移除时同步删除字典中的对应记录 options.RegisterPostEvictionCallback((evictedKey, _, reason, _) => { if (evictedKey is string keyStr) { _cacheExpirations.TryRemove(keyStr, out _); } }); _cache.Set(key, value, options); // 更新字典记录 if (absoluteExpiration.HasValue) { _cacheExpirations.TryAdd(key, absoluteExpiration.Value); } else { _cacheExpirations.TryRemove(key, out _); } return true; }
步骤3:添加获取过期时间的方法
public DateTime? GetExpiration(string key) { if (_cacheExpirations.TryGetValue(key, out var expiration)) { // 额外校验缓存是否仍存在,避免字典记录与实际缓存状态不一致 if (!_cache.TryGetValue(key, out _)) { _cacheExpirations.TryRemove(key, out _); return null; } return expiration; } return null; }
方案对比
- 方案一:实现简单,无需额外维护状态,但需要修改缓存存储结构,若已有大量现有代码调用Set方法,需同步调整Get逻辑。
- 方案二:无需修改缓存值结构,对现有Get方法无侵入,但需要处理缓存自动过期时的字典同步,代码相对复杂。
内容的提问来源于stack exchange,提问作者Can Cuma Yaman
相关产品推荐
相关产品推荐

