C# 如何在asp.net core中检索内存缓存键列表?
简明扼要。是否可以列出.Net核心Web应用程序内存缓存中的所有注册密钥C# 如何在asp.net core中检索内存缓存键列表?,c#,asp.net-mvc,caching,asp.net-core,C#,Asp.net Mvc,Caching,Asp.net Core,简明扼要。是否可以列出.Net核心Web应用程序内存缓存中的所有注册密钥 我在IMemoryCache接口中没有找到任何东西。目前在IMemoryCache接口中没有这样的方法来返回所有缓存密钥。根据评论,我认为今后不会增加这一点 引用评论 我认为这是值得怀疑的,因为这个想法的一部分 对于缓存来说,仅仅是在你问了一个问题之后的瞬间 答案可能已经改变了。也就是说,假设你有这个问题的答案 哪些键在那里?片刻之后,缓存被清除,列表被删除 您拥有的密钥的数量无效 如果您需要密钥,则应在将项目设置到缓存并
我在IMemoryCache接口中没有找到任何东西。目前在
IMemoryCache
接口中没有这样的方法来返回所有缓存密钥。根据评论,我认为今后不会增加这一点
引用评论
我认为这是值得怀疑的,因为这个想法的一部分
对于缓存来说,仅仅是在你问了一个问题之后的瞬间
答案可能已经改变了。也就是说,假设你有这个问题的答案
哪些键在那里?片刻之后,缓存被清除,列表被删除
您拥有的密钥的数量无效
如果您需要密钥,则应在将项目设置到缓存并根据需要使用时,在应用程序中维护密钥列表
下面是另一个有用的github问题
我们实现了这个概念,以支持通过正则表达式模式进行删除 可在中找到完整的实现。 这几天我们正在转移到AspNet Core,所以位置可能会移动。 在存储库中搜索
MemoryCacheManager
在.Net内核中还没有这样的东西。 以下是我的解决方法:
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());
}
var field=typeof(MemoryCache).GetProperty(“EntriesCollection”,BindingFlags.NonPublic | BindingFlags.Instance);
var collection=field.GetValue(_memoryCache)作为ICollection;
var items=新列表();
if(集合!=null)
foreach(集合中的var项)
{
var methodInfo=item.GetType().GetProperty(“键”);
var val=methodInfo.GetValue(项目);
items.Add(val.ToString());
}
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.
//获取EntriesCollection的空定义
var cacheEntriesCollectionDefinition=typeof(MemoryCache).GetProperty(“EntriesCollection”,System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//使用IMemoryCache实例填充定义。
//它需要被转换为动态,否则你不能
//由于它是对象的集合,所以可以循环使用它。
var cacheEntriesCollection=cacheEntriesCollectionDefinition.GetValue(InstanceMemoryCache)为动态;
//定义一个新的列表,我们也将添加缓存项
List cacheCollectionValues=新列表();
foreach(cacheEntriesCollection中的var cacheItem)
{
//从包含缓存项的键/值对中获取“值”
Microsoft.Extensions.Caching.Memory.ICacheEntry cacheItemValue=cacheItem.GetType().GetProperty(“值”).GetValue(cacheItem,null);
//将缓存项添加到列表中
cacheCollectionValues.Add(cacheItemValue);
}
//现在,您可以随意循环上面创建的cacheCollectionValues列表。
我知道这不是答案,但是。。。
还有一种方法可以缓存列表。大概是这样的:
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;
}
公共异步任务GetUsers()
{
var cacheKey=“getAllUserCacheKey”;
如果(_usersCache!=null&((MemoryCache)_usersCache).Count>0)
{
return\u usersCache.Get(cacheKey);
}
var users=await_userRepository.GetAll();
//设置缓存选项。
var cacheEntryOptions=new MemoryCacheEntryOptions()
.SetSlidingExpiration(时间跨度从分钟(5));
_usersCache.Set(cacheKey,users);
返回用户;
}
正如其他答案所指出的,的当前实现不公开任何允许检索所有缓存密钥的成员,尽管如果我们使用反射可以解决此问题 这个答案建立在这个基础上,通过将反射使用减少到最低限度来提高解决方案的速度,并将所有内容打包到一个扩展类中
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
使用Microsoft.Extensions.Caching.Memory;
公共静态类MemoryCacheExtensions
{
私有静态只读函数GetEntriesCollection=Delegate.CreateDelegate(
类型(Func),
typeof(MemoryCache).GetProperty(“EntriesCollection”,BindingFlags.NonPublic | BindingFlags.Instance).getMethod(true),
throwOnBindFailure:true)作为Func;
公共静态IEnumerable GetKey(此IMemoryCache memoryCache)=>
((IDictionary)GetEntriesCollection((MemoryCache)MemoryCache))。键;
公共静态IEnumerable GetKey(此IMemoryCache memoryCache)=>
GetKeys(memoryCache).OfType();
}
用法:
var cache=newmemorycache(newmemorycacheoptions());
GetOrCreate(1,ce=>“一”);
GetOrCreate(“两个”,ce=>“两个”);
foreach(缓存中的var key.GetKeys())
WriteLine($”键:'{Key}',键类型:'{Key.GetType()}'”;
foreach(缓存中的var key.GetKeys())
WriteLine($”键:'{Key}',键类型:'{Key.GetType()}'”;
输出:
Key: '1', Key type: 'System.Int32'
Key: 'two', Key type: 'System.String'
Key: 'two', Key type: 'System.String'
注:
- 反射使用减少到一个单独的调用。使用
的键时,不使用反射。当我们遍历一长串EntriesCollection
的键时,这可以节省一些时间和资源MemoryCache
- 在解决方案中,我们将
属性强制转换为MemoryCache.EntriesCollection
,尽管其支持字段IDictionary
的类型为MemoryCache.\u条目
。我们无法将其直接强制转换为该类型,因为ConcurrentDictionary
type是内部的CacheEntry
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>();
}
公共静态IEnumerable GetKeys(此IAppCache-appCache)
{
var cacheProvider=appCache.cacheProvider作为MemoryCacheProvider;
if(cacheProvider!=null)//在测试中可能是MockCacheProvider
{
变量场