13

我想开发一个接受来自用户社区的插件的应用程序,类似于 Chrome 或 Firefox 的做法。这将是一个 Web 应用程序,因此单个用户的应用程序的每个“实例”都将运行不同的插件(插件将作为单例实例加载,但仅对某些用户是“活动的”)。我计划在 .NET 中实现该应用程序,并尝试为插件模型提出一个体系结构。

这是我想要的属性:

  • 插件完全构建在我的核心应用程序之外,作为单独的程序集。
  • 插件在它们自己的“锁定”、低信任环境中运行。可能是一个单独的 AppDomain。
  • 插件只能通过我提供的 API 起作用。例如,我会将某种外观作为接口传递给它们,它们只能调用它,而不能调用任何其他程序集。我不能拥有可以在 Web 服务器上任意执行操作的插件,例如影响文件系统。
  • 插件中的致命崩溃不会影响核心应用程序的稳定性。

似乎 System.AddIn 是我最好的选择,但我不清楚如何强制加载的插件仅通过我提供的 API 工作,而不加载任何其他程序集。System.AddIn 是否提供该功能?另外,System.AddIn 可以与 ASP.NET / IIS 一起使用吗?

除了 System.Addin,我还有哪些其他选择?

4

3 回答 3

5

看起来您主要关心的是隔离(为了安全性和稳健性)。

因此,您最好的选择是在单独的 AppDomain 中激活您的插件。在此域中,您可以控制允许加载的程序集(请参阅 AppDomainSetup 类)。

您的主代码也将受到保护,不会在插件内发生任何不愉快的事情:所有插件方法都必须使用核心对象的副本(除非您传递的对象是从 MarshalByRefObject 继承的,在这种情况下,所有的赌注都是关闭的)。插件方法中的异常可以通过将所有调用包装在 try except 中,或者通过 AppDomain 的 UnhandledExcption 事件来处理。

请记住,跨越 AppDomain 边界会降低性能。该呼叫本质上是一个远程呼叫。

另一个潜在的问题是您打算如何管理 AppDomain。我从未尝试在一个进程中创建多个 AppDomain,但我预计会遇到麻烦。为单个域中的多个用户组合插件将挑战您尝试构建的保护

作为对@RationalGeek 问题的回应 - UnhandledException 事件允许这样做 - 有点。您可以在核心域和插件域中订阅此事件,但这样做存在很多不确定性 - 请参阅我引用的文章了解更多详细信息。可能更好的选择是将对 API 的每次调用包装在 try/except 中

于 2013-04-03T20:55:58.550 回答
1

您可以尝试使用 AppDomains 并处理未处理的异常。为避免 appdomain 崩溃,您必须处理AppDomain.UnhandledException

在上面的链接中,请注意以下语句

从 .NET Framework 4 开始,不会针对破坏进程状态的异常(例如堆栈溢出或访问冲突)引发此事件,除非事件处理程序是安全关键的并且具有 HandleProcessCorruptedStateExceptionsAttribute 属性。

因此,您可能需要显式处理一些配置。

我读过很多问题,声称当子域中的不同线程上发生未处理的异常时,会冒泡并关闭父域。如果是这样,那么将所有插件加载到一个单独的进程中,每个插件都有一个 appdomain 或将插件加载到单独的进程中可能是可取的。

我还遇到了关于 SO 的以下问题,我相信您会觉得很有帮助

于 2013-04-10T10:48:51.797 回答
-1

为什么不直接使用反射并在运行时发现可用的插件呢?Assembly.LoadFile 获取程序集,GetExportedTypes 获取您的对象使用 Activator.CreateInstance 创建实例

然后只需在 try 循环中运行插件,以确保它不会影响系统。尽管您将需要一些重要的架构来提供实际的稳定性。

除非您有复杂的插件管理场景,否则请远离 MEF。如果它只是允许用户使用他们的并包括你自己的一些,那就使用反射。

于 2013-04-03T20:20:02.960 回答