Welcome

首页 / 软件开发 / .NET编程技术 / WPF:用于承载第三方 .NET 插件的体系结构

WPF:用于承载第三方 .NET 插件的体系结构2014-03-10 MSDN Levi Haskell去年 11 月,Bloomberg L.P.发布了应用程序门户,它是一个应用程序平台,独立的第三 方软件开发者可借助该平台面向 Bloomberg 专业服务的 300,000 多名用户销售其基于 Microsoft .NET Framework Windows Presentation Foundation (WPF) 的应用程序。

在本文中,我们将介绍一个用来承载第三方“不受信任的”.NET 应用程序的通用体系结 构,它与 Bloomberg 应用程序门户使用的体系结构类似。附带的源代码 (archive.msdn.microsoft. com/mag201308Plugins) 包含对 .NET 插件宿主和演示插件的引用实现,该演示插件使 用 Bloomberg API 来绘制给定安全性的历史定价信息图表。

插件宿主体系结构

1 中显示的体系结构包含主应用程序进程和插件 宿主进程。


图 1 用于承载 .NET 插件的体系结构

实现插件宿主基础结构的开发人员应仔细考虑将插件宿主作为独立进程来实现的优缺点。 就应用程序门户而言,我们坚信此方法的利远大于弊,但我们会列出您需要注意的最重要因 素。

将插件宿主作为独立进程实现的优点包括:

它将主应用程序进程与插件分离开来,这将减少插件对应用程序的性能或可用性产生任何 负面影响的可能。它减小了插件阻止主应用程序的 UI 线程的风险。此外,它不太可能导致 主进程中出现内存或任何其他关键资源泄漏的情况。此方法还降低了因编写得非常糟糕的插 件导致出现“托管”或“未托管”未处理异常,从而减慢主应用程序进程的可能性。

通过应用与 The Chromium Projects(有关详细信息,请参阅 bit.ly/k4V3wq)使用的沙盒技术类似的沙盒技术,有可 能提高整个解决方案的安全性。

它为主应用程序进程留出了更多的虚拟内存空间(这对于 32 位进程来说更为重要,此类 进程受到进程用户模式代码的 2GB 可用虚拟内存空间的限制)。

它允许您使用 .NET 插件扩展非 .NET 应用程序的功能。

缺点主要与整体实施复杂性的增加相关:

您需要实现单独的进程间通信 (IPC) 机制(当主应用程序进程和插件宿主具有不同的版 本或部署循环时,应特别注意 IPC 接口的版本控制)。

您必须管理插件宿主进程的生存期。

在为不受信任的第三方插件设计宿主进程时,实现用户安全性是需要考虑的主要问题之一 。定义适当的安全体系结构这一主题有必要单独进行讨论,不在本文的范围内。

.NET 应用程序域(System.AppDomain 类)提供了用于承载 .NET 插件的全面而可靠的解 决方案。

AppDomain 具有以下强大功能:

一个 AppDomain 中的类型安全的对象无法直接访问另一个 AppDomain 中的对象,从而允 许宿主强制将一个插件与另一个插件隔离开。

可以单独配置 AppDomain,从而允许宿主通过提供不同的配置设置来为不同类型的插件微 调 AppDomain。

可以卸载 AppDomain,从而允许宿主卸载插件和所有关联的程序集,以非特定于域的形式 加载的程序集除外(使用加载程序优化选项 LoaderOptimization.Multi­Domain 或 LoaderOptimization.MultiDomainHost)。此功能通过允许宿主卸载在托管代码中失败的插 件来让宿主进程变得更可靠。

主应用程序和插件宿主进程可使用各种可用的 IPC 机制之一(例如,COM、命名管道、 Windows Communication Foundation (WCF) 等)来进行交互。在建议的体系结构中,主应用 程序进程的角色是管理复合 UI 的创建,并提供针对插件的各种应用程序服务。2 显示 Bloomberg Launchpad 视图,该视图表示此类复合 UI 。“Stealth Analytics”组件由 Bloomberg 应用程序门户托管的基于 WPF 的插件创建和呈 现,所有其他组件由基于 Win32 的 Bloomberg Terminal 应用程序创建和呈现。主应用程序 进程通过插件控制器代理将命令发送到插件宿主进程。

图 2 示例复合 UI

插件控制器正在插件宿主进程的默认 AppDomain 中运行,它负责处理从主应用程序进程 接收的命令,从而将插件加载到专用 AppDomains 并管理其生存期。

示例源代码提供了对体系结构的引用实现,并包含托管基础结构以及 SAPP 和 DEMO 插件 。