在 IMemoryCache 上调用扩展方法 GetOrCreateAsync 时是否可以避免缓存?

Iss*_*ram 7 .net c# asynchronous memorycache .net-core

我正在使用 来IMemoryCache缓存从身份服务器检索到的令牌。

过去我使用过库GetOrCreateAsync中提供的扩展方法Microsoft.Extensions.Caching.Abstractions。这非常有帮助,因为我可以同时定义函数和到期日期。

但是,使用令牌时,在请求完成之前我不会知道x 秒后的过期值。我想通过根本不缓存令牌来解释不存在的值的用例。

我尝试过以下方法

var token = await this.memoryCache.GetOrCreateAsync<string>("SomeKey", async cacheEntry =>
{
    var jwt = await GetTokenFromServer();
    var tokenHasValidExpireValue = int.TryParse(jwt.ExpiresIn, out int tokenExpirationSeconds);
    
    if (tokenHasValidExpireValue)
    {
        cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(tokenExpirationSeconds);
    }
    else // Do not cache value.  Just return it.
    {
        cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(0); //Exception thrown.  Value needs to be positive.
    }

    return jwt.token;
}
Run Code Online (Sandbox Code Playgroud)

如您所见,当我尝试设置 no time 过期时,会引发异常TimeSpan.FromSeconds(0)

除了分别调用GetSet方法之外,还有其他方法可以解决这个问题吗?如果可能的话我想使用该GetOrCreateAsync方法。

Dav*_*d L 5

您实际上无法使用当前扩展来完成此操作,因为它始终会在调用工厂方法之前创建一个条目。也就是说,您可以以与GetOrCreateAsync.

public static class CustomMemoryCacheExtensions
{
    public static async Task<TItem> GetOrCreateIfValidTimestampAsync<TItem>(
        this IMemoryCache cache, object key, Func<Task<(int, TItem)>> factory)
    {
        if (!cache.TryGetValue(key, out object result))
        {
            (int tokenExpirationSeconds, TItem factoryResult) = 
                await factory().ConfigureAwait(false);

            if (tokenExpirationSeconds <= 0)
            {
                // if the factory method did not return a positive timestamp,
                // return the data without caching.
                return factoryResult;
            }

            // since we have a valid timestamp:
            // 1. create a cache entry
            // 2. Set the result
            // 3. Set the timestamp
            using ICacheEntry entry = cache.CreateEntry(key);

            entry.Value = result;
            entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(tokenExpirationSeconds);
        }

        return (TItem)result;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以以非常类似的方式调用扩展方法:

var memoryCache = new MemoryCache(new MemoryCacheOptions());
var token = await memoryCache.GetOrCreateIfValidTimestampAsync<string>("SomeKey", async () =>
{
    var jwt = await GetTokenFromServer();
    var tokenHasValidExpireValue = int.TryParse(jwt.ExpiresIn, out int tokenExpirationSeconds);

    return (tokenExpirationSeconds, jwt.token);
}
Run Code Online (Sandbox Code Playgroud)