从另一个AppDomain程序集复制方法并从CurrentDomain执行它

在大图中,我试图从主域中的dll执行方法,但之后,卸载该DLL。 到目前为止我已经创建了新的AppDomain加载了Assembly \ MaxStackSize ,使用MarshalByRefObject我将该方法的主体和MaxStackSize获取到主域,在那里创建DynamicMethod ,重新创建其中的主体并调用它。 但是当我调用它时,我得到exception: System.BadImageFormatException: Signature is not IMAGE_CEE_CS_CALLCONV_LOCAL_SIG

获取并调用它的代码:

 DynamicMethod method = new DynamicMethod( "func", typeof( void ), new Type[ 0 ] ); var info = method.GetDynamicILInfo( ); info.SetCode( marshal.GetILCode( ), marshal.GetMaxStackSize()); info.SetLocalSignature( SignatureHelper.GetMethodSigHelper( CallingConventions.Standard, typeof( void ) ).GetSignature( ) ); method.Invoke( null, new object[ 0 ] ); //<-- exception here 

marshal是Proxy类型的对象。 可能需要的一些注意事项:

  1. 我正在获取\调用的方法是public static void Run();
  2. 尝试调用该方法的AppDomain和加载dll \ assembly的AppDomain具有相同的引用。

编辑

我通过GetSignature方法将第一个字节更改为0x07来修复签名。 但是存在新问题System.InvalidProgramException: Common Language Runtime detected an invalid program.

您的实现有一个很大的错误, MethodBase.GetMethodBody的字节数组不可移植

使用OpCodes.Call或OpCodes.Callvirt的方法调用会产生几个字节,一个指示调用类型(call / callvirt),后跟四个字节,表示元数据令牌。 在这种情况下,此标记可以解析为Int32,并使用Module.ResolveMethod解析为MethodBase。

请注意,这些元数据令牌是在编译时生成的; 它们可能在编译之间有所不同。 (虽然它是编译器的实现细节,但我相信它们只是基于编译期间看到的方法顺序的自动递增数字。)

这意味着您尝试使用的实际字节包含动态模块中无效的元数据标记。 它们可能指向具有与您期望的签名不同的现有方法,或者可能在您的模块中根本不存在。

您需要解析il代码并再次发出所有内容,从而生成新的有效元数据标记。