c# - 从另一个 AppDomain 的程序集中复制方法并从 CurrentDomain 执行它

标签 c# reflection.emit

总的来说,我试图从主域中的 dll 执行方法,但之后,卸载该 dll。到目前为止,我已经创建了新的 AppDomain 并在那里加载了 Assembly\dll,使用 MarshalByRefObject 我获取了主体和 MaxStackSize 到主域的方法,在那里创建了 DynamicMethod,在其中重新创建了主体并调用了它。 但是当我调用它时出现异常: System.BadImageFormatException:签名不是 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

marshalProxy 类型的对象. 可能需要的一些注意事项:

  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 代码并再次发出所有内容,从而生成新的有效元数据 token 。

关于c# - 从另一个 AppDomain 的程序集中复制方法并从 CurrentDomain 执行它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24350769/

相关文章:

c# - Property Getter 的反射发射

c# - 如何使用 IL Emit 定义相互引用的两种类型

.net - MethodBuilder.DefineParameter 无法设置参数名称的原因?

c# - 为什么在 lambda 表达式中使用迭代变量不好

c# - 在 C# 最佳实践中处理字典

c# - 无法从类库中读取 App.config 值

reflection - 如何发送到具有 'params' 构造函数的类?

c# - 如何在 .NET 3.5 中重用线程

c# - 尝试在 Debug模式下运行项目时出现 "Could not find file...\bin\Debug"错误

.net - AssemblyBuilder 引用程序集