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>();
}

 

posted @ 2024-12-03 10:33  ziff123  阅读(1)  评论(0编辑  收藏  举报