Common.Cache.MemoryCache 2.1.0

dotnet add package Common.Cache.MemoryCache --version 2.1.0
                    
NuGet\Install-Package Common.Cache.MemoryCache -Version 2.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Common.Cache.MemoryCache" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Common.Cache.MemoryCache" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Common.Cache.MemoryCache" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Common.Cache.MemoryCache --version 2.1.0
                    
#r "nuget: Common.Cache.MemoryCache, 2.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Common.Cache.MemoryCache@2.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Common.Cache.MemoryCache&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Common.Cache.MemoryCache&version=2.1.0
                    
Install as a Cake Tool

Common.Cache.MemoryCache

Common.Cache.MemoryCache 是一个基于 Microsoft.Extensions.Caching.Memory 的轻量封装,提供统一的缓存读写、批量删除和按模式删除能力。

功能特性

  • 基于 ASP.NET Core IMemoryCache
  • 支持字符串、对象、集合等多种缓存值
  • 支持 GetOrCreateAsync
  • 支持批量删除和按通配符删除
  • 支持获取当前由 Provider 管理的全部缓存键
  • 支持 .NET 6.0 / 7.0 / 8.0 / 9.0 / 10.0

安装

Install-Package Common.Cache.MemoryCache

或:

dotnet add package Common.Cache.MemoryCache

服务注册

推荐使用 AddMemoryCacheStore

services.AddMemoryCacheStore(options =>
{
    options.DefaultExpiry = TimeSpan.FromSeconds(30);
    options.CacheEmptyCollections = false;
    options.FailThrowException = true; // 缓存操作失败时是否抛出异常(默认为true)
});

旧方法 AddMemoryCacheExtension 已标记为过时,但仍可继续使用:

services.AddMemoryCacheExtension(options =>
{
    options.DefaultExpiry = TimeSpan.FromSeconds(30);
    options.CacheEmptyCollections = false;
    options.FailThrowException = true; // 缓存操作失败时是否抛出异常(默认为true)
});

基本使用

public class MyService
{
    private readonly ICacheProvider _cacheProvider;

    public MyService(ICacheProvider cacheProvider)
    {
        _cacheProvider = cacheProvider;
    }

    public async Task<UserInfo> GetUserAsync(string userId)
    {
        return await _cacheProvider.GetOrCreateAsync(
            $"user:{userId}",
            async () => await LoadUserFromDatabase(userId),
            TimeSpan.FromMinutes(10));
    }
}

读写缓存

await _cacheProvider.SetAsync("name", "azrng", TimeSpan.FromMinutes(5));

var name = await _cacheProvider.GetAsync("name");
var count = await _cacheProvider.GetAsync<int>("count");
var user = await _cacheProvider.GetAsync<UserInfo>("user:1");

GetOrCreateAsync

var count = await _cacheProvider.GetOrCreateAsync(
    "counter",
    () => 0,
    TimeSpan.FromMinutes(1));
var user = await _cacheProvider.GetOrCreateAsync(
    "user:1",
    async () => await LoadUserFromDatabase("1"),
    TimeSpan.FromMinutes(10));

批量操作

await _cacheProvider.RemoveAsync(new[] { "user:1", "user:2", "user:3" });

await _cacheProvider.RemoveMatchKeyAsync("user:*");

var allKeys = ((IMemoryCacheProvider)_cacheProvider).GetAllKeys();

var allValues = await ((IMemoryCacheProvider)_cacheProvider).GetAllAsync(allKeys);

await ((IMemoryCacheProvider)_cacheProvider).RemoveAllKeyAsync();

配置项

MemoryConfig 提供以下配置:

  • DefaultExpiry: 默认过期时间,默认值为 5 秒
  • CacheEmptyCollections: 是否缓存空集合和空字符串,默认值为 true
  • FailThrowException: 缓存操作失败时是否抛出异常,默认值为 true

行为说明

1. 合法默认值会被正常缓存

从当前实现开始,0falseDateTime.MinValue 这类合法业务值会被正常缓存,不再被误判为空值。

await _cacheProvider.SetAsync("bool:false", false);
var value = await _cacheProvider.GetAsync<bool>("bool:false"); // false

2. CacheEmptyCollections 只控制空集合和空字符串

CacheEmptyCollections = false 时:

  • null 不会缓存
  • 空字符串不会缓存
  • 空集合不会缓存
  • 0false 等合法默认值仍然会缓存

3. 异常处理可通过配置控制

2.1.0 开始,可通过 FailThrowException 配置控制缓存操作失败时的行为:

  • true(默认):记录日志并抛出异常,避免把真实故障误判成”缓存未命中”
  • false:记录日志并返回默认值,不抛出异常,提供更灵活的错误处理策略

4. 并发访问同一个 Key 时会做单 Key 同步

同一个 Key 在高并发下首次未命中时,Provider 会按 Key 做同步,避免多个线程同时重复执行工厂方法。

这能减少数据库或远程调用的重复压力。

5. RemoveMatchKeyAsync 使用通配符语义

RemoveMatchKeyAsync 不是正则表达式,而是通配符匹配:

  • * 匹配任意多个字符
  • ? 匹配任意单个字符
  • [] 匹配指定字符范围

示例:

await _cacheProvider.RemoveMatchKeyAsync("user:*");
await _cacheProvider.RemoveMatchKeyAsync("order:2026-03-??");

6. GetAllKeys 只返回当前 Provider 管理的键

GetAllKeys 不再通过反射读取 MemoryCache 内部私有字段,而是返回通过当前 Provider 写入并跟踪的键集合。

这意味着:

  • 通过 IMemoryCache 直接写入的键不会出现在 GetAllKeys
  • 通过 Provider 删除、覆盖、驱逐的键会同步更新跟踪集合
  • 实现更稳定,不依赖 .NET 运行时内部结构

注意事项

  • 不建议使用 IEnumerable<T>IQueryable<T>IAsyncEnumerable<T> 作为 GetOrCreateAsync<T>T
  • 如果需要缓存集合,请优先使用 List<T> 或数组
  • SetAsync<T>(key, null) 会返回 false,不会写入缓存

版本更新记录

  • 2.1.0
    • 新增FailThrowException 配置项,允许控制缓存操作失败时的行为
      • true(默认):记录日志并抛出异常,与 2.0.0 行为一致
      • false:记录日志并返回默认值,不抛出异常,提供更灵活的错误处理策略
    • 优化GetOrCreateAsync 支持 FailThrowException 配置,统一异常处理行为
  • 2.0.0
    • 破坏性更新GetOrCreateAsync 发生异常时不再吞掉异常并返回 default,改为记录日志后继续抛出异常
    • 破坏性更新RemoveMatchKeyAsync 改为按通配符语义匹配,支持 *?[],不再直接把输入当作正则表达式
    • 破坏性更新GetAllKeys 改为返回当前 Provider 管理并跟踪的键,不再依赖反射读取 MemoryCache 内部私有字段
    • 修复:支持缓存合法默认值,例如 0falseDateTime.MinValue
    • 修复:GetOrCreateAsync 增加单 Key 并发保护,避免并发未命中时重复执行工厂方法
    • 修复:RemoveAsync(IEnumerable<string>) 过滤空 key 和重复 key,并返回更准确的删除数量
    • 优化:依赖注入注册改为复用同一个作用域内的 MemoryCacheProvider 实例
  • 1.3.2
    • 更新异常信息输出
  • 1.3.1
    • 更新批量删除缓存的日志输出
  • 1.3.0
    • 修复 .NET 8 模糊匹配生效问题
    • 引用 .NET 10 正式包
  • 1.3.0-beta9
    • 更新 .NET 10
  • 1.3.0-beta8
    • 修复设置不缓存空值时的问题
  • 1.3.0-beta7
    • 修复 GetOrCreateAsync 读取不到缓存仍写入的问题
  • 1.3.0-beta6
    • 更新命名空间
  • 1.3.0-beta5
    • 支持 .NET 9
    • 移除对 netstandard2.1 的支持
    • 更新注入方法 AddMemoryCacheStore
  • 1.3.0-beta4
    • 修改方法 KeyDeleteInBatchAsyncRemoveMatchKeyAsync
    • 修改方法 GetAllCacheKeysGetAllKeys
    • 修改方法 RemoveCacheAllAsyncRemoveAllKeyAsync
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 69 3/26/2026
2.0.0 104 3/23/2026
1.3.2 312 12/17/2025
1.3.1 464 12/10/2025
1.3.0 367 11/30/2025
1.3.0-beta9 177 11/6/2025
1.3.0-beta8 208 10/9/2025
1.3.0-beta7 244 8/28/2025
1.3.0-beta5 204 7/14/2025
1.3.0-beta4 419 6/5/2024
1.3.0-beta3 183 2/9/2024
1.3.0-beta2 169 2/8/2024
1.3.0-beta11 292 11/12/2025
1.3.0-beta10 123 11/7/2025
1.3.0-beta1 297 11/14/2022
1.2.0 570 11/12/2022
1.1.1 628 7/9/2022
1.1.0 731 11/11/2020
1.0.1 627 10/9/2020
1.0.0 648 10/8/2020