update MemoryCache hack extension to support the new implementation

This commit is contained in:
13xforever 2024-10-15 19:00:50 +05:00
parent bc07b7700a
commit 2d47dccc12
No known key found for this signature in database
GPG Key ID: 2B2A36B482FE70C5
2 changed files with 29 additions and 8 deletions

View File

@ -8,8 +8,15 @@ namespace CompatBot.Utils;
internal static class MemoryCacheExtensions
{
private static readonly object throaway = new object();
public static List<T> GetCacheKeys<T>(this MemoryCache memoryCache)
{
// idk why it requires access before it populates the internal state
memoryCache.TryGetValue("str", out _);
memoryCache.TryGetValue(throaway, out _);
// get the internal state object
var stateField = memoryCache.GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.FirstOrDefault(fi => fi.Name == "_coherentState");
@ -17,20 +24,27 @@ internal static class MemoryCacheExtensions
if (coherentState is null)
{
Config.Log.Error($"Looks like {nameof(MemoryCache)} internals have changed");
return new();
return [];
}
var field = coherentState.GetType()
// get the actual underlying key-value object
var stringField = coherentState.GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.FirstOrDefault(fi => fi.Name == "_entries");
if (field is null)
.FirstOrDefault(fi => fi.Name == "_stringEntries");
var nonStringField = coherentState.GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.FirstOrDefault(fi => fi.Name == "_nonStringEntries");
if (stringField is null || nonStringField is null)
{
Config.Log.Error($"Looks like {nameof(MemoryCache)} internals have changed");
return new();
return [];
}
var value = (IDictionary?)field.GetValue(coherentState);
return value?.Keys.OfType<T>().ToList() ?? new List<T>();
// read the keys
var value = typeof(T) == typeof(string)
? (IDictionary?)stringField.GetValue(coherentState)
: (IDictionary?)nonStringField.GetValue(coherentState);
return value?.Keys.OfType<T>().ToList() ?? [];
}
public static Dictionary<TKey, ICacheEntry?> GetCacheEntries<TKey>(this MemoryCache memoryCache)

View File

@ -14,7 +14,14 @@ public class MemoryCacheExtensionTests
var cache = new MemoryCache(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromHours(1) });
Assert.That(cache.GetCacheKeys<int>(), Is.Empty);
cache.Set(13, "val13");
const string testVal = "vale13";
cache.Set(13, testVal);
Assert.Multiple(() =>
{
Assert.That(cache.TryGetValue(13, out string expectedVal), Is.True);
Assert.That(expectedVal, Is.EqualTo(testVal));
}
);
Assert.That(cache.GetCacheKeys<int>(), Has.Count.EqualTo(1));
}