<PackageReference Include="Castle.Core" Version="4.3.0" />

InvocationHelper

public static class InvocationHelper
using Castle.Core.Internal; using Castle.DynamicProxy.Generators; using System; using System.Collections.Generic; using System.Reflection; namespace Castle.DynamicProxy.Internal { public static class InvocationHelper { private struct CacheKey : IEquatable<CacheKey> { public MethodInfo Method { get; } public Type Type { get; } public CacheKey(MethodInfo method, Type type) { Method = method; Type = type; } public bool Equals(CacheKey other) { if ((object)Method == other.Method) return (object)Type == other.Type; return false; } public override bool Equals(object obj) { if (obj == null) return false; object obj2; if ((obj2 = obj) is CacheKey) { CacheKey other = (CacheKey)obj2; return Equals(other); } return false; } public override int GetHashCode() { return (((Method != (MethodInfo)null) ? Method.GetHashCode() : 0) * 397) ^ ((Type != (Type)null) ? Type.GetHashCode() : 0); } } private static readonly Dictionary<CacheKey, MethodInfo> cache = new Dictionary<CacheKey, MethodInfo>(); private static readonly Lock lock = Lock.Create(); public static MethodInfo GetMethodOnObject(object target, MethodInfo proxiedMethod) { if (target == null) return null; return GetMethodOnType(target.GetType(), proxiedMethod); } public static MethodInfo GetMethodOnType(Type type, MethodInfo proxiedMethod) { if (type == (Type)null) throw new ArgumentNullException("type"); using (IUpgradeableLockHolder upgradeableLockHolder = lock.ForReadingUpgradeable()) { MethodInfo fromCache = GetFromCache(proxiedMethod, type); if (!(fromCache != (MethodInfo)null)) { upgradeableLockHolder.Upgrade(); fromCache = GetFromCache(proxiedMethod, type); if (!(fromCache != (MethodInfo)null)) { fromCache = ObtainMethod(proxiedMethod, type); PutToCache(proxiedMethod, type, fromCache); return fromCache; } return fromCache; } return fromCache; } } private static MethodInfo GetFromCache(MethodInfo methodInfo, Type type) { CacheKey key = new CacheKey(methodInfo, type); cache.TryGetValue(key, out MethodInfo value); return value; } private static MethodInfo ObtainMethod(MethodInfo proxiedMethod, Type type) { Type[] array = null; if (proxiedMethod.IsGenericMethod) { array = proxiedMethod.GetGenericArguments(); proxiedMethod = proxiedMethod.GetGenericMethodDefinition(); } Type declaringType = proxiedMethod.DeclaringType; MethodInfo methodInfo = null; if (declaringType.GetTypeInfo().IsInterface) { InterfaceMapping runtimeInterfaceMap = type.GetTypeInfo().GetRuntimeInterfaceMap(declaringType); int num = Array.IndexOf(runtimeInterfaceMap.InterfaceMethods, proxiedMethod); methodInfo = runtimeInterfaceMap.TargetMethods[num]; } else { MethodInfo[] allInstanceMethods = MethodFinder.GetAllInstanceMethods(type, BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in allInstanceMethods) { if (MethodSignatureComparer.Instance.Equals(methodInfo2.GetBaseDefinition(), proxiedMethod)) { methodInfo = methodInfo2; break; } } } if (methodInfo == (MethodInfo)null) throw new ArgumentException($"""{proxiedMethod}""{type}"""); if (array == null) return methodInfo; return methodInfo.MakeGenericMethod(array); } private static void PutToCache(MethodInfo methodInfo, Type type, MethodInfo value) { CacheKey key = new CacheKey(methodInfo, type); cache.Add(key, value); } } }