C# 动态加载/卸载程序集

Posted

技术标签:

【中文标题】C# 动态加载/卸载程序集【英文标题】:C# Dynamic Load/Unload Assemblies 【发布时间】:2018-01-23 16:55:02 【问题描述】:

我正在尝试将动态编译的程序集加载到其他 Appdomain 并使用 Appdomain.Unload() 方法卸载它。我试过这个:

  public class RemoteLoader : MarshalByRefObject
    
        public void LoadAndExecute(string assemblyName)
        
            Assembly pluginAassembly = AppDomain.CurrentDomain.Load(assemblyName);

            foreach (Type type in pluginAassembly.GetTypes())
            
                if (type.GetInterface("IScript") != null)
                
                    IScriptableComponent component = new DummyComponent();
                    var instance = (IScript)Activator.CreateInstance(type, null, null);
                    instance.Run(component);
                
            
        
    

“IScript”是我的自定义脚本 然后,点击按钮调用编译过程并设置RemoteLoader对象:

 private void StartButton_Click(object sender, EventArgs e)
    
        
        var compiledAssemblyPath = Path.Combine(Environment.CurrentDirectory, ScriptsDirectory, CompiledScriptsAssemblyName);
       
        var scriptFiles = Directory.EnumerateFiles(ScriptsDirectory, "*.cs", SearchOption.AllDirectories).ToArray();

        var scriptAssembly = Helper.CompileAssembly(scriptFiles, compiledAssemblyPath);
        
        AppDomain appDomainPluginB = AppDomain.CreateDomain("appDomainPluginB");

        RemoteLoader loader = (RemoteLoader)appDomainPluginB.CreateInstanceAndUnwrap(
           AssemblyName.GetAssemblyName(compiledAssemblyPath).Name,
           "Scripts.MyCustomScript");

        loader.LoadAndExecute(CompiledScriptsAssemblyName);
        AppDomain.Unload(appDomainPluginB);

    

首先,VS 显示 Scripts.MyCustomScript 不可序列化的异常。所以我为此添加了 [Serializable],现在 VS 显示“Scripts.MyCustomScript”无法设置为 RemoteLoader 的对象的异常。

【问题讨论】:

【参考方案1】:

您正在尝试为Scripts.MyCustomScript 创建一个实例并将其转换为RemoteLoader。这是错误的。您想从appDomainPluginB 域创建RemoteLoader 的实例。因此,您应该为CreateInstanceAndUnwrap 指定所需的类型。

RemoteLoader loader = (RemoteLoader)appDomainPluginB.CreateInstanceAndUnwrap(
    typeof(RemoteLoader).Assembly.FullName,
    typeof(RemoteLoader).FullName);

然后你可以从IScript实现的插件类型处理和创建实例。

【讨论】:

正在进行中。现在,当 loader.LoadAndExecute 启动时,它会显示 HRESULT: 0x80131047 异常,表明无法加载已编译的程序集或其引用之一... 您在“Assembly pluginAassembly = AppDomain.CurrentDomain.Load(assemblyName);”这一行收到错误 我不明白为什么编译的程序集不在当前域中,尝试搜索这个问题.. 因为您创建了一个名为“appDomainPluginB”的单独域尝试使用Assembly.Load 将 AppDomain.CurrentDomain.Load 更改为 Assembly.Load 的同样问题,assemblyName 是我编译程序集的完整路径...

以上是关于C# 动态加载/卸载程序集的主要内容,如果未能解决你的问题,请参考以下文章

C#动态加载dll 时程序集的卸载问题

C# 通过 AppDomain 应用程序域实现程序集动态卸载或加载

C# 通过 AppDomain 应用程序域实现程序集动态卸载或加载

c# .NET 加载/卸载程序集,同时保持相同的会话

C#.Net 如何动态加载与卸载程序集(.dll或者.exe)

C#中如何动态加载和卸载DLL