在Mono中将程序集加载到单独的AppDomain中会导致FileNotFoundException

时间:2018-01-25 15:21:08

标签: c# mono

我正在为Discord bot开发一种插件系统。现在我使用Mono作为我的运行时使用macOS,我一直在寻找使用单独的AppDomains来加载和管理每个插件。插件本身确实有依赖关系,但这些已经加载到主appdomain中。所以这就是我的问题:

  1. 我试图迭代当前域中加载的程序集并将它们加载到我的单独AppDomain中,因此插件的依赖项已经加载。这会在尝试加载所述依赖项时导致FileNotFoundException(即使我将它们指向exe目录中的正确路径。)

  2. 我试过没有这样做,只是通过将插件dll加载到一个单独的AppDomain中,看看它是否会自动解决。仍然会抛出FileNotFoundException。

  3. 我尝试按照dependendies的顺序手动创建一个数组(在我的应用程序的情况下,Newtonsoft.Json - > DSharpPlus - > Bot.CommandManager)。由于缺少依赖性,我甚至无法加载Newtonsoft.Json。

  4. 现在,我将原始字节加载到流读取器并将其传递到AppDomain.Load,以确保FileNotFoundException来自缺少依赖性而不是实际文件丢失。文件在那里,仍在domain.Load

  5. 上抛出FileNotFoundException

    我能够成功加载插件的唯一方法就是使用Assembly.Load并且不要担心AppDomains在我更新内容并想要卸载/重新加载插件之前效果很好。这是我需要使用AppDomain的地方。我有点迷茫,这是我目前的代码迭代。对于每个插件都有一个单独的AppDomain可能是非常不必要的,但我现在正在使用它。

    private void SetupAppDomain()
        {
            string path = Directory.GetCurrentDirectory() + "/modules/";
            Console.WriteLine(path);
            List<string> installedModules = new List<string>();
            string[] files = Directory.GetFiles(path);
            foreach(string modulePath in files)
            {
                try
                {
                    AppDomain domain = AppDomain.CreateDomain(Path.GetFileName(modulePath), AppDomain.CurrentDomain.Evidence);
                    StreamReader reader = new StreamReader(modulePath, System.Text.Encoding.GetEncoding(1252), false);
                    byte[] b = new byte[reader.BaseStream.Length];
                    reader.BaseStream.Read(b, 0, System.Convert.ToInt32(reader.BaseStream.Length));
                    domain.Load(b); //this throws the FileNotFoundException
                    Assembly[] a = domain.GetAssemblies();
                    int index = 0;
                    for (int i = 0; i < a.Length; i++)
                    {
                        if(a[i].GetName().Name + ".dll" == Path.GetFileName(modulePath))
                        {
                            index = i;
                            break;
                        }
                    }
                    installedModules.Add(a[index].GetName().Name);
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }
        }
    

    最糟糕的情况是,我可以回到原来的做法,当我想重新加载程序集时只需要重新启动机器人。

0 个答案:

没有答案