在新的应用程序域中启动第三方 DLL 中存在的方法

Posted

技术标签:

【中文标题】在新的应用程序域中启动第三方 DLL 中存在的方法【英文标题】:launch a method present in third party DLL in a new appdomain 【发布时间】:2013-02-22 10:32:42 【问题描述】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DoCallBack

    class Program
    
        static void Main(string[] args)
        
            AppDomain newDomain = AppDomain.CreateDomain("New Domain");
            Console.WriteLine(newDomain.BaseDirectory);
            newDomain.DoCallBack(new CrossAppDomainDelegate(SayHello));
            AppDomain.Unload(newDomain);
        
    

我想在新的应用程序域中调用 SayHello() 方法。让我们假设,HelloMethod DLL 是第三方的,我没有代码。我只有组装。但我知道它有 SayHello() 方法。我能做什么?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HelloMethod

    class Program
    
        static void Main(string[] args)
        
        

        static void SayHello()
        
            Console.WriteLine("Hi from " + AppDomain.CurrentDomain.FriendlyName);
        
    

在这个当前代码中,它给出错误“当前上下文中不存在名称'SayHello'”

【问题讨论】:

【参考方案1】:

如果程序集尚未加载,则必须加载它。有两种方法:

    从您的项目中引用程序集并简单地做:

    newDomain.DoCallBack(new CrossAppDomainDelegate(HelloMethod.Program.SayHello));
    

    如果您不介意在自己的项目中引用第三方程序集,则可以。这也意味着您在编译时就知道要调用的程序集、类型和方法。

    自行加载第三方程序集并执行具体方法:

    /// <summary>
    /// To be executed in the new AppDomain using the AppDomain.DoCallBack method.
    /// </summary>
    static void GenericCallBack()
                           
        //These can be loaded from somewhere else like a configuration file.
        var thirdPartyAssemblyFileName = "ThirdParty.dll";
        var targetTypeFullName = "HelloMethod.Program";
        var targetMethodName = "SayHello";
    
        try
        
            var thirdPartyAssembly = Assembly.Load(AssemblyName.GetAssemblyName(thirdPartyAssemblyFileName));
    
            var targetType = thirdPartyAssembly.GetType(targetTypeFullName);
    
            var targetMethod = targetType.GetMethod(targetMethodName);
    
            //This will only work with a static method!           
            targetMethod.Invoke(null, null);             
        
        catch (Exception e)
        
            Console.WriteLine("Callback failed. Error info:");
            Console.WriteLine(e);
        
    
    

    如果您正在寻找一种更灵活的方式从第三方程序集中调用公共静态方法,则可以使用此方法。请注意,几乎所有内容都在 try-catch 中,因为这里很多东西都可能出错。这是因为这些“反射”调用中的每一个都可能引发异常。最后注意,要使这种方法发挥作用,第三方程序集及其所有依赖项都位于应用程序的基本目录或私有 bin 路径之一中。

【讨论】:

感谢分配,new CrossAppDomainDelegate 是必要的吗?为什么没有这个我们可以运行? @SHRI 有必要!编译器为您声明的每个委托类型生成代码。 CrossAppDomainDelegate 可能让编译器知道委托应该从 MarshalByRefObject 派生以允许跨 AppDomain 通信。这是我的猜测。重要的是您需要使用 CrossAppDomainDelegate。

以上是关于在新的应用程序域中启动第三方 DLL 中存在的方法的主要内容,如果未能解决你的问题,请参考以下文章

在新的 Visual Studio Express (C++ prefrred) 项目中使用旧版 (VB6) DLL

无法在新的 appDomain 中加载程序集

如何在新的意图活动完成后启动其余方法

在新的 AppDomain 中加载插件

完整的动态加载卸载程序集的解决方案

在新的应用程序域中运行时,如何将标准输出转换为 mstest 输出?