Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在asp.net core中检索内存缓存键列表?_C#_Asp.net Mvc_Caching_Asp.net Core - Fatal编程技术网

C# 如何在asp.net core中检索内存缓存键列表?

C# 如何在asp.net core中检索内存缓存键列表?,c#,asp.net-mvc,caching,asp.net-core,C#,Asp.net Mvc,Caching,Asp.net Core,简明扼要。是否可以列出.Net核心Web应用程序内存缓存中的所有注册密钥 我在IMemoryCache接口中没有找到任何东西。目前在IMemoryCache接口中没有这样的方法来返回所有缓存密钥。根据评论,我认为今后不会增加这一点 引用评论 我认为这是值得怀疑的,因为这个想法的一部分 对于缓存来说,仅仅是在你问了一个问题之后的瞬间 答案可能已经改变了。也就是说,假设你有这个问题的答案 哪些键在那里?片刻之后,缓存被清除,列表被删除 您拥有的密钥的数量无效 如果您需要密钥,则应在将项目设置到缓存并

简明扼要。是否可以列出.Net核心Web应用程序内存缓存中的所有注册密钥


我在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
    。我们无法将其直接强制转换为该类型,因为
    CacheEntry
    type是内部的

我在使用MemoryCacheExtensions,建议显示 ,将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>();
}
公共静态IEnumerable GetKeys(此IAppCache-appCache)
{
var cacheProvider=appCache.cacheProvider作为MemoryCacheProvider;
if(cacheProvider!=null)//在测试中可能是MockCacheProvider
{
变量场