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

LazyCache如何全局阻止null项加入缓存 消除重复冗余代码

统一实现null缓存项自动过期的方案

原生IMemoryCache没有内置null值自动过期的能力,你可以通过封装通用扩展方法把重复的判断逻辑抽离,一次编写全局生效,不需要每次写缓存操作都重复判空。

实现步骤

首先封装针对IMemoryCache的通用扩展方法,把null值判空、过期时间设置的逻辑统一收口:

public static class MemoryCacheExtensions
{
    /// <summary>
    /// 获取缓存值,不存在时执行委托生成;值为null时自动设置立即过期不缓存,非null时应用指定有效时长
    /// </summary>
    /// <param name="cache">缓存实例</param>
    /// <param name="key">缓存键</param>
    /// <param name="factory">缓存值生成委托</param>
    /// <param name="validExpire">非null值的有效过期时长</param>
    /// <param name="cacheNullValue">是否缓存null值,默认不缓存</param>
    public static T GetOrAddWithAutoExpire<T>(
        this IMemoryCache cache,
        object key,
        Func<T> factory,
        TimeSpan validExpire,
        bool cacheNullValue = false)
    {
        return cache.GetOrAdd(key, entry =>
        {
            var result = factory();
            // null值按规则处理
            if (!cacheNullValue && result == null)
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.Zero;
            }
            else
            {
                entry.AbsoluteExpirationRelativeToNow = validExpire;
            }
            return result;
        });
    }

    /// <summary>
    /// 支持自定义ICacheEntry配置的重载,适配需要设置滑动过期、缓存优先级等特殊规则的场景
    /// </summary>
    public static T GetOrAddWithAutoExpire<T>(
        this IMemoryCache cache,
        object key,
        Func<ICacheEntry, T> factory,
        TimeSpan validExpire,
        bool cacheNullValue = false)
    {
        return cache.GetOrAdd(key, entry =>
        {
            var result = factory(entry);
            if (!cacheNullValue && result == null)
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.Zero;
            }
            else
            {
                // 若委托内已经手动配置了过期时间,可加判断不覆盖,按需调整即可
                if (entry.AbsoluteExpirationRelativeToNow == null)
                {
                    entry.AbsoluteExpirationRelativeToNow = validExpire;
                }
            }
            return result;
        });
    }
}

使用方式

封装完成后,所有缓存操作直接调用扩展方法即可,完全不需要重复编写null判断逻辑,原来的代码可以简化为:

// 非null值缓存1天,null值自动不缓存
output = _cache.GetOrAddWithAutoExpire(
    "GetRecordUri" + 123, 
    () => internalGetRecordUri(), 
    TimeSpan.FromDays(1)
);

额外说明

  • 你原来代码中用负时间戳实现立即过期的效果和TimeSpan.Zero完全一致,用TimeSpan.Zero代码可读性更高
  • 如果后续要调整null值的缓存策略,比如给null值设置10秒短过期防止缓存穿透,只需要修改扩展方法里的逻辑,所有调用场景会自动同步生效
  • 扩展方法预留了cacheNullValue参数,特殊场景需要缓存null值时传true即可,灵活性足够

内容的提问来源于stack exchange,提问作者CodeMan03

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:42:58