[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: CLSCompliant(true)]
[assembly: NeutralResourcesLanguageAttribute("zh-CN")]
[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints]
[assembly: StringFreezing]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security;
[TypeLibType(TypeLibTypeFlags.FHidden | TypeLibTypeFlags.FRestricted)]
public static partial class VirtualProxy
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal static ModuleBuilder MainDynamicModule
{
get;
set;
}
[SecuritySafeCritical]
static VirtualProxy()
{
VirtualProxy.MainDynamicModule = VirtualProxy.CreateDynamicModule();
}
[SecuritySafeCritical]
private static ModuleBuilder CreateDynamicModule()
{
AssemblyBuilder _asm = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Path.GetRandomFileName()), AssemblyBuilderAccess.RunAndSave);
return _asm.DefineDynamicModule(_asm.FullName);
}
[SecuritySafeCritical]
private static TypeBuilder CreateDynamicType()
{
return VirtualProxy.MainDynamicModule.DefineType(Path.GetRandomFileName(), TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, null, null);
}
[SecuritySafeCritical]
internal static void CreateDynamicMethods(Type objRefType)
{
MethodInfo[] _mets = objRefType.GetMethods();
foreach (MethodInfo _met in _mets)
{
if (_met.DeclaringType == objRefType)
{
VirtualProxy.CreateDynamicMethod(_met, VirtualProxy.CreateDynamicType());
}
}
}
[SecuritySafeCritical]
private static Type[] GetDynamicParameterType(ParameterInfo[] args)
{
Type[] _params = new Type[args.Length + 1];
for (int i = 1; i <= args.Length; i++)
_params[i] = args[i - 1].ParameterType;
_params[0] = typeof(object); return _params;
}
[SuppressUnmanagedCodeSecurity]
private static void CreateDynamicMethod(MethodInfo met, TypeBuilder builder)
{
ParameterInfo[] _params = met.GetParameters();
MethodBuilder _callback = builder.DefineMethod(builder.Name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, met.ReturnType, VirtualProxy.GetDynamicParameterType(_params));
ILGenerator _il = _callback.GetILGenerator();
_il.DeclareLocal(typeof(object[]));
// 必须过滤VOID型,否则引发CLR/JIT内部错误
if (met.ReturnType != typeof(void))
{
_il.DeclareLocal(met.ReturnType);
}
_il.Emit(OpCodes.Nop); // PUSH ECX
_il.Emit(OpCodes.Ldc_I4, _params.Length + 2);
_il.Emit(OpCodes.Newarr, typeof(object));
_il.Emit(OpCodes.Stloc_0);
_il.Emit(OpCodes.Ldloc_0);
_il.Emit(OpCodes.Ldc_I4, 0);
_il.Emit(OpCodes.Ldarg, 0);
_il.Emit(OpCodes.Box, typeof(object));
_il.Emit(OpCodes.Stelem_Ref);
for (int i = 1; i <= _params.Length; i++) // PUSH EBX+(8 + i * sizeof(void*))
{
_il.Emit(OpCodes.Ldloc_0); // 无论如何,您不可以BOX与调用PARAM不同类型
_il.Emit(OpCodes.Ldc_I4, i);
_il.Emit(OpCodes.Ldarg, i);
_il.Emit(OpCodes.Box, _params[i - 1].ParameterType);
_il.Emit(OpCodes.Stelem_Ref);
}
_il.Emit(OpCodes.Ldloc_0);
_il.Emit(OpCodes.Ldc_I4, _params.Length + 1);
_il.Emit(OpCodes.Ldstr, met.Name);
_il.Emit(OpCodes.Box, typeof(object));
_il.Emit(OpCodes.Stelem_Ref);
_il.Emit(OpCodes.Ldloc_0);
_il.Emit(OpCodes.Call, typeof(VirtualProxy).GetMethod("VirtualInvokeMember"));
if (met.ReturnType == typeof(void)) // MOV EAX, DWORD PTR[EBP-(8 + sizeof(void*)]
{
_il.Emit(OpCodes.Pop);
}
else // 不可以移除现行计算堆栈顶部的(EAX)的值,一旦使用会引发CLR ClrSystemExecuteEngine发生难以解决的故障
{
_il.Emit(OpCodes.Unbox_Any, met.ReturnType);
_il.Emit(OpCodes.Stloc_1);
_il.Emit(OpCodes.Ldloc_1);
}
// ExecutionEngineException
_il.Emit(OpCodes.Ret);
DirectedManagedMethods _metredir = new DirectedManagedMethods(); // 函数流程导向
_metredir.Install(met.MethodHandle.GetFunctionPointer(), (builder.CreateType()).GetMethod(builder.Name));
}
[SuppressUnmanagedCodeSecurity]
public static object VirtualInvokeMember(object[] args) // 您不可以修改函数返回值类型,不论被导向.NET函数需不需要返回
{
int len = args.Length - 1;
object[] _retVal = new object[len - 1];
for (int i = 1; i < len; i++)
{
_retVal[i - 1] = args[i];
}
object _sender = args[0];
IRefObjProvider _refObj = (IRefObjProvider)_sender;
return _refObj.InvokeMember(_sender, (string)args[len], _retVal);
}
}