ProxyUtil
using Castle.Core.Internal;
using Castle.DynamicProxy.Generators;
using Castle.DynamicProxy.Internal;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Castle.DynamicProxy
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public static class ProxyUtil
{
private static readonly SynchronizedDictionary<Assembly, bool> internalsVisibleToDynamicProxy = new SynchronizedDictionary<Assembly, bool>();
public static TDelegate CreateDelegateToMixin<[System.Runtime.CompilerServices.Nullable(2)] TDelegate>(object proxy)
{
return (TDelegate)(object)CreateDelegateToMixin(proxy, typeof(TDelegate));
}
public static Delegate CreateDelegateToMixin(object proxy, Type delegateType)
{
if (proxy == null)
throw new ArgumentNullException("proxy");
if (delegateType == (Type)null)
throw new ArgumentNullException("delegateType");
if (!delegateType.IsDelegateType())
throw new ArgumentException("Type is not a delegate type.", "delegateType");
MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
MethodInfo methodInfo = proxy.GetType().GetMember("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Cast<MethodInfo>()
.FirstOrDefault((MethodInfo m) => MethodSignatureComparer.Instance.EqualParameters(m, invokeMethod));
if (methodInfo == (MethodInfo)null)
throw new MissingMethodException("The proxy does not have an Invoke method that is compatible with the requested delegate type.");
return Delegate.CreateDelegate(delegateType, proxy, methodInfo);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public static object GetUnproxiedInstance(object instance)
{
IProxyTargetAccessor proxyTargetAccessor = instance as IProxyTargetAccessor;
if (proxyTargetAccessor != null)
return proxyTargetAccessor.DynProxyGetTarget();
return instance;
}
public static Type GetUnproxiedType(object instance)
{
IProxyTargetAccessor proxyTargetAccessor = instance as IProxyTargetAccessor;
if (proxyTargetAccessor != null) {
object obj = proxyTargetAccessor.DynProxyGetTarget();
if (obj != null) {
if (obj == instance)
return instance.GetType().BaseType;
instance = obj;
}
}
return instance.GetType();
}
[System.Runtime.CompilerServices.NullableContext(2)]
public static bool IsProxy(object instance)
{
return instance is IProxyTargetAccessor;
}
public static bool IsProxyType(Type type)
{
return typeof(IProxyTargetAccessor).IsAssignableFrom(type);
}
public static bool IsAccessible(MethodBase method)
{
if (IsAccessibleMethod(method))
return IsAccessibleType(method.DeclaringType);
return false;
}
public static bool IsAccessible(MethodBase method, [System.Runtime.CompilerServices.Nullable(2)] [NotNullWhen(false)] out string message)
{
if (IsAccessible(method)) {
message = null;
return true;
}
message = CreateMessageForInaccessibleMethod(method);
return false;
}
public static bool IsAccessible(Type type)
{
return IsAccessibleType(type);
}
internal static bool AreInternalsVisibleToDynamicProxy(Assembly asm)
{
return internalsVisibleToDynamicProxy.GetOrAdd(asm, (Assembly a) => asm.GetCustomAttributes<InternalsVisibleToAttribute>().Any((InternalsVisibleToAttribute attr) => attr.AssemblyName.Contains(ModuleScope.DEFAULT_ASSEMBLY_NAME)));
}
internal static bool IsAccessibleType(Type target)
{
if (target.IsPublic || target.IsNestedPublic)
return true;
bool isNested = target.IsNested;
bool flag = isNested && (target.IsNestedAssembly || target.IsNestedFamORAssem);
if (((!target.IsVisible && !isNested) | flag) && AreInternalsVisibleToDynamicProxy(target.Assembly))
return true;
return false;
}
internal static bool IsAccessibleMethod(MethodBase method)
{
MethodAttributes methodAttributes = method.Attributes & MethodAttributes.MemberAccessMask;
if ((uint)(methodAttributes - 2) <= 1)
return AreInternalsVisibleToDynamicProxy(method.DeclaringType.Assembly);
if ((uint)(methodAttributes - 4) <= 2)
return true;
return false;
}
internal static bool IsInternal(MethodBase method)
{
if (!method.IsAssembly) {
if (method.IsFamilyAndAssembly)
return !method.IsFamilyOrAssembly;
return false;
}
return true;
}
private static string CreateMessageForInaccessibleMethod(MethodBase inaccessibleMethod)
{
Assembly assembly = inaccessibleMethod.DeclaringType.Assembly;
string str = $"""{inaccessibleMethod}""";
string str2 = ExceptionMessageBuilder.CreateInstructionsToMakeVisible(assembly);
return str + str2;
}
}
}