InvocationHelper
using Castle.Core.Internal;
using Castle.DynamicProxy.Generators;
using System;
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 ((((object)Method != null) ? Method.GetHashCode() : 0) * 397) ^ (((object)Type != null) ? Type.GetHashCode() : 0);
}
}
private static readonly SynchronizedDictionary<CacheKey, MethodInfo> cache = new SynchronizedDictionary<CacheKey, MethodInfo>();
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");
CacheKey key = new CacheKey(proxiedMethod, type);
return cache.GetOrAdd(key, (CacheKey ck) => ObtainMethod(proxiedMethod, type));
}
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);
}
}
}