2012-06-06 101 views
3

在处理插件程序集的子目录时,存在一个众所周知的问题,即一旦它们尝试从其子目录加载它们各自的依赖项,这些程序集就无法加载。一种解决方案是在初始化时在AppDomain中加载其PrivateBinPath设置在它们的AppDomainSetup对象中的插件。但是,这会导致关于编组/跨AppDomain通信的其他困难,特别是如果插件应该提供一些GUI。插件AppDomains解决方法

当安全性方面的优先级较低(非关键性的实用程序应用程序,由于错误的插件导致崩溃时没有严重问题),我有以下想法:在应用程序启动时,应该搜索所有插件目录,并且应该创建一个新的AppDomain,它的bin路径中包含这些目录。然后,整个应用程序及其GUI在新的AppDomain中运行,以及所有插件。

在特定情况下,是否有任何理由避免该解决方案?或者有什么理由可以解释为什么这个解决方案不可行?

+0

我认为,如果你的主界面在相同的AppDomain作为插件运行,如果插件崩溃,主UI可能会崩溃。你使用插件框架还是“RYO”? – IAbstract

+0

@IAbstract:即使在另一个AppDomain中运行,也不要崩溃插件通常也会导致主UI失败?毕竟,插件中引发的任何异常都会跨AppDomain边界进行编组,并使主应用程序退出,除非我处理异常。在我的特殊情况下,这是RYO - 我研究了Addin框架并阅读了许多关于它的文章,但它们都提到了核心应用程序和插件之间极简主义的界面,而不是复杂和深层嵌套的对象层次结构。需要转移。 –

回答

1

考虑到您描述的情况,我不知道与您的第二个域的提案相关的任何问题。但是,您也可以通过使用Assembly.LoadFrom搜索addins子目录并从那里加载程序集来调查在初始域上处理程序集加载失败的可能性。一个可能的设置对于这一点,在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); 
} 
+0

这只适用于托管程序集吗?更具体地说,当我手动在子目录中找到插件程序集时,会自动发现相同子目录中的非托管程序库? –

+0

'Assembly.LoadFrom'允许找到并加载该路径的进一步依赖关系,因为路径信息由上下文维护。但是,对于混音中的非托管程序集,我不太乐意给你任何确定性。 –

+0

我对此进行了进一步的阅读并做了一些测试。看起来确实好像不仅是托管的,而且如果它们与加载了'LoadFrom'的程序集位于相同的目录中,则会发现非托管库。但是,阅读[docs](http://msdn.microsoft.com/en-us/library/1009fa28.aspx),似乎'LoadFrom'专门将程序集加载到所谓的* load-from *上下文中,而* load *上下文由于各种原因将是优选的。另一方面,我没有看到任何方式从自定义位置将程序集加载到* load *上下文中。 –