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

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 static readonly Dictionary<KeyValuePair<MethodInfo, Type>, MethodInfo> cache = new Dictionary<KeyValuePair<MethodInfo, Type>, 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 ((object)type == null) throw new ArgumentNullException("type"); using (IUpgradeableLockHolder upgradeableLockHolder = lock.ForReadingUpgradeable()) { MethodInfo fromCache = GetFromCache(proxiedMethod, type); if ((object)fromCache == null) { upgradeableLockHolder.Upgrade(); fromCache = GetFromCache(proxiedMethod, type); if ((object)fromCache == null) { fromCache = ObtainMethod(proxiedMethod, type); PutToCache(proxiedMethod, type, fromCache); return fromCache; } return fromCache; } return fromCache; } } private static MethodInfo GetFromCache(MethodInfo methodInfo, Type type) { KeyValuePair<MethodInfo, Type> key = new KeyValuePair<MethodInfo, Type>(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 (System.Reflection.IntrospectionExtensions.GetTypeInfo(declaringType).IsInterface) { InterfaceMapping runtimeInterfaceMap = System.Reflection.IntrospectionExtensions.GetTypeInfo(type).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 ((object)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) { KeyValuePair<MethodInfo, Type> key = new KeyValuePair<MethodInfo, Type>(methodInfo, type); cache.Add(key, value); } } }