InvocationHelper
using Castle.Core.Internal;
using Castle.DynamicProxy.Generators;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Castle.DynamicProxy.Internal
{
internal static class InvocationHelper
{
private struct CacheKey : IEquatable<CacheKey>
{
public MethodInfo Method {
[IsReadOnly]
get;
}
public Type Type {
[IsReadOnly]
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;
if (obj is CacheKey) {
CacheKey other = (CacheKey)obj;
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 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 (type == (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 (declaringType.IsInterface) {
InterfaceMapping interfaceMap = type.GetInterfaceMap(declaringType);
int num = Array.IndexOf(interfaceMap.InterfaceMethods, proxiedMethod);
methodInfo = interfaceMap.TargetMethods[num];
} else {
MethodInfo[] allInstanceMethods = type.GetAllInstanceMethods();
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);
}
}
}