.NET 9 Preview 1 中 MemoryCache 的更新
Intro
.NET 9 Preview 1 中為 MemoryCache 添加了一個
Keys
內容,我們可以透過它來獲取 memory cache 中的緩存的 key list 了,另外新增了一個帶
MemoryCacheEntryOptions
參數的
GetOrCreate(Async)
多載方法
Sample
Keys Sample
新增的 API:
public classMemoryCache
{
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 isstring 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
輸出結果如下:
再來看一下使用依賴註入的範例,大體上差不多,只是我們需要轉換一下型別,因為這個
Keys
是定義在
MemoryCache
型別上,
IMemoryCache
介面並未定義
Console.WriteLine("MemoryCache keys dependency injection sample");
usingvar 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 isstring 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());
}
輸出結果如下:
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");
usingvar services = new ServiceCollection()
.AddMemoryCache()
.BuildServiceProvider();
var memoryCache = services.GetRequiredService<IMemoryCache>();
var key = "user:2:roles";
FetchValue();
Thread.Sleep(1000);
FetchValue();
Thread.Sleep(3000);
FetchValue();
voidFetchValue()
{
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
沒有設定過期時間,另外一個設定了三秒的過期時間,輸出結果如下:
可以看到
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