Skip to content

Commit

Permalink
✨🎨优化Microsoft.Extensions.Caching.Memory 8
Browse files Browse the repository at this point in the history
  • Loading branch information
LemonNoCry committed Oct 24, 2024
1 parent fcb4982 commit 1f5efce
Showing 1 changed file with 38 additions and 16 deletions.
54 changes: 38 additions & 16 deletions Blog.Core.Common/Caches/Extensions/MemoryCacheExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,48 @@ public static class MemoryCacheExtensions
{
#region Microsoft.Extensions.Caching.Memory_6_OR_OLDER

private static readonly Lazy<Func<MemoryCache, object>> GetEntries6 = new(() => (Func<MemoryCache, object>)Delegate.CreateDelegate(
typeof(Func<MemoryCache, object>),
typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true),
throwOnBindFailure: true));
private static readonly Lazy<Func<MemoryCache, object>> GetEntries6 = new(() =>
(Func<MemoryCache, object>)Delegate.CreateDelegate(typeof(Func<MemoryCache, object>),
typeof(MemoryCache).GetProperty("EntriesCollection", BindingFlags.NonPublic | BindingFlags.Instance)
?.GetGetMethod(true) ?? throw new InvalidOperationException("Cannot find property 'EntriesCollection' on MemoryCache."),
throwOnBindFailure: true));

#endregion

#region Microsoft.Extensions.Caching.Memory_7_OR_NEWER

private static readonly Lazy<Func<MemoryCache, object>> GetCoherentState = new(() =>
CreateGetter<MemoryCache, object>(typeof(MemoryCache)
.GetField("_coherentState", BindingFlags.NonPublic | BindingFlags.Instance)));
private static readonly Lazy<Func<MemoryCache, object>> GetCoherentState7 = new(() =>
CreateGetter<MemoryCache, object>(typeof(MemoryCache)
.GetField("_coherentState", BindingFlags.NonPublic | BindingFlags.Instance)));

private static readonly Lazy<Func<object, IDictionary>> GetEntries7 = new(() =>
CreateGetter<object, IDictionary>(typeof(MemoryCache)
.GetNestedType("CoherentState", BindingFlags.NonPublic)
.GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance)));
CreateGetter<object, IDictionary>(typeof(MemoryCache)
.GetNestedType("CoherentState", BindingFlags.NonPublic)?
.GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance)));

#endregion

#region Microsoft.Extensions.Caching.Memory_8_OR_NEWER

private static readonly Lazy<Func<MemoryCache, object>> GetCoherentState8 = new(() =>
CreateGetter<MemoryCache, object>(typeof(MemoryCache)
.GetField("_coherentState", BindingFlags.NonPublic | BindingFlags.Instance)));

private static readonly Lazy<Func<object, IDictionary>> GetEntries8 = new(() =>
CreateGetter<object, IDictionary>(typeof(MemoryCache)
.GetNestedType("CoherentState", BindingFlags.NonPublic)?
.GetField("_stringEntries", BindingFlags.NonPublic | BindingFlags.Instance)));

#endregion

private static Func<TParam, TReturn> CreateGetter<TParam, TReturn>(FieldInfo field)
{
var methodName = $"{field.ReflectedType.FullName}.get_{field.Name}";
if (field == null)
{
throw new ArgumentNullException(nameof(field), "Field cannot be null.");
}

var methodName = $"{field.ReflectedType!.FullName}.get_{field.Name}";
var method = new DynamicMethod(methodName, typeof(TReturn), new[] { typeof(TParam) }, typeof(TParam), true);
var ilGen = method.GetILGenerator();
ilGen.Emit(OpCodes.Ldarg_0);
Expand All @@ -38,12 +59,13 @@ private static Func<TParam, TReturn> CreateGetter<TParam, TReturn>(FieldInfo fie
return (Func<TParam, TReturn>)method.CreateDelegate(typeof(Func<TParam, TReturn>));
}

#endregion

private static readonly Func<MemoryCache, IDictionary> GetEntries =
Assembly.GetAssembly(typeof(MemoryCache)).GetName().Version.Major < 7
? (Func<MemoryCache, IDictionary>)(cache => (IDictionary)GetEntries6.Value(cache))
: cache => GetEntries7.Value(GetCoherentState.Value(cache));
Assembly.GetAssembly(typeof(MemoryCache))?.GetName().Version?.Major switch
{
< 7 => cache => (IDictionary)GetEntries6.Value(cache),
7 => cache => GetEntries7.Value(GetCoherentState7.Value(cache)),
_ => cache => GetEntries8.Value(GetCoherentState8.Value(cache)),
};

public static ICollection GetKeys(this IMemoryCache memoryCache) =>
GetEntries((MemoryCache)memoryCache).Keys;
Expand Down

0 comments on commit 1f5efce

Please sign in to comment.