简明扼要。是否可以在.Net Core Web应用程序中列出内存缓存中的所有注册密钥?
我在IMemoryCache界面中找不到任何内容。
答案 0 :(得分:6)
.Net Core中还没有这样的东西。 这是我的解决方法:
var field = typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance);
var collection = field.GetValue(_memoryCache) as ICollection;
var items = new List<string>();
if (collection != null)
foreach (var item in collection)
{
var methodInfo = item.GetType().GetProperty("Key");
var val = methodInfo.GetValue(item);
items.Add(val.ToString());
}
答案 1 :(得分:4)
正如其他答案所指出的那样,Microsoft.Extensions.Caching.Memory.MemoryCache的当前实现并未公开任何允许检索所有缓存键的成员,尽管如果使用反射可以解决问题。
此答案建立在MarkM的答案上,它通过将反射的使用量减少到最低来提高解决方案的速度。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Caching.Memory;
public static class MemoryCacheExtensions
{
private static readonly Func<MemoryCache, object> GetEntriesCollection = Delegate.CreateDelegate(
typeof(Func<MemoryCache, object>),
typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true),
throwOnBindFailure: true) as Func<MemoryCache, object>;
public static IEnumerable GetKeys(this IMemoryCache memoryCache) =>
((IDictionary)GetEntriesCollection((MemoryCache)memoryCache)).Keys;
public static IEnumerable<T> GetKeys<T>(this IMemoryCache memoryCache) =>
GetKeys(memoryCache).OfType<T>();
}
用法:
var cache = new MemoryCache(new MemoryCacheOptions());
cache.GetOrCreate(1, ce => "one");
cache.GetOrCreate("two", ce => "two");
foreach (var key in cache.GetKeys())
Console.WriteLine($"Key: '{key}', Key type: '{key.GetType()}'");
foreach (var key in cache.GetKeys<string>())
Console.WriteLine($"Key: '{key}', Key type: '{key.GetType()}'");
输出:
Key: '1', Key type: 'System.Int32'
Key: 'two', Key type: 'System.String'
Key: 'two', Key type: 'System.String'
注意:
GetEntriesCollection
delegate。当我们使用EntriesCollection
的键时,不使用反射。当我们遍历MemoryCache
的键的长集合时,这可以节省一些时间和资源。EntriesCollection
属性投射到IDictionary
,尽管其后备字段_entries
的类型为ConcurrentDictionary<object, CacheEntry>
。我们无法将其直接转换为该类型,因为CacheEntry
类型是内部类型。答案 2 :(得分:2)
目前在IMemoryCache
接口中没有这样的方法来返回所有缓存键。根据{{3}}评论,我认为将来不会添加。
我认为这是可行的,因为部分想法是可行的 缓存就是你提出一个问题后的片刻 答案本可以改变。也就是说,假设你有答案 哪些键存在 - 片刻之后清除缓存和列表 你拥有的钥匙是无效的。
如果您需要密钥,则应在将项目设置为缓存时维护应用程序中的密钥列表,并根据需要使用该密钥。
答案 3 :(得分:1)
我们实现了这个概念,以便通过正则表达式模式进行删除。
完整的实施可以在Saturn72
github repository中找到。
这些天我们正在转向AspNet Core,因此位置可能会发生变化。
在存储库中搜索MemoryCacheManager
This is the current location
答案 4 :(得分:1)
MarkM的答案对我而言并不奏效,也无法将结果转换为ICollection,但是我接受了这个想法并提出了对我来说非常有效的方法。希望它也可以帮助其他人:
// Get the empty definition for the EntriesCollection
var cacheEntriesCollectionDefinition = typeof(MemoryCache).GetProperty("EntriesCollection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
// Populate the definition with your IMemoryCache instance.
// It needs to be cast as a dynamic, otherwise you can't
// loop through it due to it being a collection of objects.
var cacheEntriesCollection = cacheEntriesCollectionDefinition.GetValue(instanceIMemoryCache) as dynamic;
// Define a new list we'll be adding the cache entries too
List<Microsoft.Extensions.Caching.Memory.ICacheEntry> cacheCollectionValues = new List<Microsoft.Extensions.Caching.Memory.ICacheEntry>();
foreach (var cacheItem in cacheEntriesCollection)
{
// Get the "Value" from the key/value pair which contains the cache entry
Microsoft.Extensions.Caching.Memory.ICacheEntry cacheItemValue = cacheItem.GetType().GetProperty("Value").GetValue(cacheItem, null);
// Add the cache entry to the list
cacheCollectionValues.Add(cacheItemValue);
}
// You can now loop through the cacheCollectionValues list created above however you like.
答案 5 :(得分:0)
答案 6 :(得分:0)
我知道这不是答案,但是... 还有另一种方法,您可以缓存列表。像这样:
public async Task<List<User>> GetUsers()
{
var cacheKey = "getAllUserCacheKey";
if (_usersCache != null && ((MemoryCache)_usersCache).Count > 0)
{
return _usersCache.Get<List<User>>(cacheKey);
}
var users = await _userRepository.GetAll();
// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes(5));
_usersCache.Set(cacheKey, users);
return users;
}
答案 7 :(得分:0)
我正在使用MemoryCacheExtensions,建议in roxton’s answer显示以下内容的密钥列表 lazyCache,将MemoryCache包装为MemoryCacheProvider
public static IEnumerable<string> GetKeys(this IAppCache appCache)
{
var cacheProvider = appCache.CacheProvider as MemoryCacheProvider;
if (cacheProvider != null) //may be MockCacheProvider in tests
{
var field = typeof(MemoryCacheProvider).GetField("cache", BindingFlags.NonPublic | BindingFlags.Instance);
var memoryCache = field.GetValue(cacheProvider) as MemoryCache;
return memoryCache.GetKeys<string>();
}
return new List<string>();
}