.NET 9 Preview 1 中 MemoryCache 的更新

.NET 9 Preview 1 中 MemoryCache 的更新

Intro

.NET 9 Preview 1 中为 MemoryCache 添加了一个 Keys 属性,我们可以通过它来获取 memory cache 中的缓存的 key list 了,另外新增了一个带 MemoryCacheEntryOptions 参数的 GetOrCreate(Async) 重载方法

Sample

Keys Sample

新增的 API:

public class MemoryCache
{
    public System.Collections.Generic.IEnumerable<object> Keys { get; }
}

来看下使用示例:

Console.WriteLine("MemoryCache keys non-di sample");
var memoryCache = new MemoryCache(new MemoryCacheOptions());
memoryCache.Set("user:1:roles", "user,manager");
memoryCache.Set("user:1:permission", "read,write");
memoryCache.Set("user:2:roles", "user");
memoryCache.Set("user:2:permission", "read");
foreach (var cacheKey in memoryCache.Keys)
{
    Console.WriteLine(cacheKey.ToString());
    if (cacheKey is string cacheKeyStr && cacheKeyStr.StartsWith("user:2:"))
    {
        memoryCache.Remove(cacheKey);
    }
}

Console.WriteLine("some keys had been removed");
foreach (var cacheKey in ((MemoryCache)memoryCache).Keys)
{
    Console.WriteLine(cacheKey.ToString());
}

这个示例是直接 new 不使用依赖注入的方式,这里模拟了清除用户缓存的一个操作,将用户 2 的缓存删除并打印所有的 cache key

输出结果如下:

8c93d6f83abde6dd76996446b3d0debf.png

keys-non-di-sample-output

再来看一下使用依赖注入的示例,大体上差不多,只是我们需要转换一下类型,因为这个 Keys 是定义在 MemoryCache 类型上,IMemoryCache 接口并未定义

Console.WriteLine("MemoryCache keys dependency injection sample");
using var services = new ServiceCollection()
    .AddMemoryCache()
    .BuildServiceProvider();
var memoryCache = services.GetRequiredService<IMemoryCache>();
memoryCache.Set("user:1:roles", "user,manager");
memoryCache.Set("user:1:permission", "read,write");
memoryCache.Set("user:2:roles", "user");
memoryCache.Set("user:2:permission", "read");
foreach (var cacheKey in ((MemoryCache)memoryCache).Keys)
{
    Console.WriteLine(cacheKey.ToString());
    if (cacheKey is string cacheKeyStr && cacheKeyStr.StartsWith("user:2:"))
    {
        memoryCache.Remove(cacheKey);
    }
}

Console.WriteLine("some keys had been removed");
foreach (var cacheKey in ((MemoryCache)memoryCache).Keys)
{
    Console.WriteLine(cacheKey.ToString());
}

输出结果如下:

6453b9d98e66a984ce17b8e5517e4b12.png

keys-di-sample-output

GetOrCreate(Async) override

新的 API 定义如下:

namespace Microsoft.Extensions.Caching.Memory {
     public static class CacheExtensions {
+        public static TItem? GetOrCreate<TItem>(this IMemoryCache cache, object key, Func<ICacheEntry, TItem> factory, MemoryCacheEntryOptions? createOptions);

+        public static Task<TItem?> GetOrCreateAsync<TItem>(this IMemoryCache cache, object key, Func<ICacheEntry, Task<TItem>> factory, MemoryCacheEntryOptions? createOptions);
     }
 }

在原来的 GetOrCreate/GetOrCreateAsync 方法的基础上增加了 MemoryCacheEntryOptions 参数,这样我们可以在 options 参数设置缓存的过期时间等,我们 factory 方法就能比较简单了

使用示例如下:

Console.WriteLine("MemoryCache keys dependency injection sample");
using var services = new ServiceCollection()
    .AddMemoryCache()
    .BuildServiceProvider();
var memoryCache = services.GetRequiredService<IMemoryCache>();

var key = "user:2:roles";
FetchValue();
Thread.Sleep(1000);
FetchValue();
Thread.Sleep(3000);
FetchValue();

void FetchValue()
{    
    memoryCache.GetOrCreate("no-expiration", _ =>
        {
            Console.WriteLine("fetch value from source for no-expiration key");
            return "user";
        });

    memoryCache.GetOrCreate(key, _ =>
        {
            Console.WriteLine("fetch value from source");
            return "user";
        },
        new MemoryCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3) });
}

这里有两个缓存,用于对比设置和不设置的区别,no-expiration 没有设置过期时间,另外一个设置了三秒的过期时间,输出结果如下:

f2069098696c023f947654fe229a7d1f.png

可以看到 fetch value from source 出现了两次,第一次调用的时候缓存不存所以从 source 去取走了 factory 的逻辑,最后一次缓存过期了所以再次从 source 拿了一次,而 no-expiration key 因为没有过期时间,所以只有在第一次取得时候从 source 取,后面都是从缓存获取

这个 API 的实现比较简单,蹭了一个 PR,哈哈

References

  • https://github.com/dotnet/runtime/issues/36554

  • https://github.com/dotnet/runtime/pull/94992/files

  • https://github.com/dotnet/runtime/issues/92101

  • https://github.com/dotnet/runtime/pull/94335

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值