You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:47:29