插件 AppDomains 解决方法
Posted
技术标签:
【中文标题】插件 AppDomains 解决方法【英文标题】:Plugin AppDomains Workaround 【发布时间】:2012-06-06 23:28:10 【问题描述】:在处理它们自己的子目录中的插件程序集时,有一个众所周知的问题,即这些程序集一旦尝试从其子目录中加载各自的依赖项,就会无法加载。一种解决方案是在 AppDomains 中加载插件,这些插件在初始化时将其 PrivateBinPath
设置在其 AppDomainSetup
对象中。但是,这会导致有关编组/跨 AppDomain 通信的其他困难,特别是如果插件应该提供一些 GUI。
当安全方面的优先级较低(非关键实用程序应用程序,由于错误插件导致崩溃时没有严重问题),我有以下想法:在应用程序启动时,应搜索所有插件目录,并且应该创建一个新的 AppDomain,在其 bin 路径中包含这些目录。然后,整个应用程序及其 GUI 与所有插件一起在新的 AppDomain 中运行。
在给定的情况下,是否有任何理由避免该解决方案?或者是否有任何原因导致该解决方案甚至不可行?
【问题讨论】:
我认为如果你的主 UI 和插件在同一个 AppDomain 中运行,如果插件崩溃,主 UI 很可能会崩溃。您使用的是插件框架还是“RYO”? @IAbstract:即使在另一个 AppDomain 中运行,插件崩溃通常不会导致主 UI 崩溃吗?毕竟,插件中抛出的任何异常都会跨 AppDomain 边界进行编组,并使主应用程序退出,除非我处理异常。在我的特殊情况下,这是 RYO - 我已经研究了 Addin Framework 并阅读了许多关于它的文章,但它们都提到了核心应用程序和插件之间相当简约的接口,而不是我将要介绍的复杂和深度嵌套的对象层次结构需要转移。 【参考方案1】:考虑到您描述的场景,我不知道与您的第二个域提案相关的任何问题。但是,您也可以通过搜索自己的插件子目录并使用Assembly.LoadFrom
从那里加载程序集来研究在初始域上处理程序集加载失败的可能性。
可能的设置示例,其中必须实现 FindAssemblyByName
以搜索所有可能的位置:
static void Main(string[] args)
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
// ...
static Assembly CurrentDomain_AssemblyResolve(
object sender,
ResolveEventArgs e)
var assemblyName = new AssemblyName(e.Name);
string assemblyFilePath = FindAssemblyByName(assemblyName);
if (string.IsNullOrEmpty(assemblyFilePath))
return null;
return Assembly.LoadFrom(assemblyFilePath);
【讨论】:
这仅适用于托管程序集吗?更具体地说,当我在子目录中手动找到插件程序集时,是否会自动发现同一子目录中的非托管库?Assembly.LoadFrom
允许找到并加载对该路径的进一步依赖,因为路径信息由上下文维护。但是,由于混合了非托管程序集,我不愿意给你任何确定性。
我已经进一步阅读并做了一些测试。如果它们与使用LoadFrom
加载的程序集位于同一目录中,那么似乎不仅可以找到托管库,而且还可以找到非托管库。但是,阅读docs,似乎LoadFrom
专门将程序集加载到所谓的 load-from 上下文中,而 load 上下文对于很多原因。另一方面,我看不到任何方法可以将程序集从自定义位置加载到该 load 上下文中。以上是关于插件 AppDomains 解决方法的主要内容,如果未能解决你的问题,请参考以下文章
具有插件和多租户支持的 ASP.NET MVC 应用程序以及单独的 AppDomains?