blog.core MemoryCacheExtensions 为空处理
using System.Collections; using System.Reflection; using System.Reflection.Emit; using Microsoft.Extensions.Caching.Memory; namespace Blog.Core.Common.Caches.Extensions; 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) ?? 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>> 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))); #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) { if (field == null) { return 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); ilGen.Emit(OpCodes.Ldfld, field); ilGen.Emit(OpCodes.Ret); return (Func<TParam, TReturn>)method.CreateDelegate(typeof(Func<TParam, TReturn>)); } //TODO,服务器上用的是net8,却用要GetEntries7。这边判断是否为空,不为空用GetEntries7,为空用GetEntries8 private static readonly Func<MemoryCache, IDictionary> GetEntries = cache => { if (GetEntries7.Value != null) { return GetEntries7.Value(GetCoherentState7.Value(cache)); } else { return GetEntries8.Value(GetCoherentState8.Value(cache)); } }; //TODO,服务器上用的是net8,却用要GetEntries7. //private static readonly Func<MemoryCache, IDictionary> GetEntries = // Assembly.GetAssembly(typeof(MemoryCache))?.GetName().Version?.Major switch // { // < 7 => cache => (IDictionary)GetEntries6.Value(cache), // _ => cache => GetEntries7.Value(GetCoherentState7.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; public static IEnumerable<T> GetKeys<T>(this IMemoryCache memoryCache) => memoryCache.GetKeys().OfType<T>(); }