我想开发一个接受用户社区插件的应用程序,类似于Chrome或Firefox的插件。这将是一个Web应用程序,因此单个用户的应用程序的每个“实例”将运行不同的插件(插件将作为单例实例加载,但仅对某些用户“活动”)。我计划在.NET中实现该应用程序,并试图为插件模型提出一个架构。
以下是我想要的属性:
似乎System.AddIn是我最好的选择,但我不清楚如何强制加载的插件只能通过我提供的API工作,而不是加载任何其他程序集。 System.AddIn是否提供该功能?另外,System.AddIn可以与ASP.NET / IIS一起使用吗?
除了System.Addin,我还有哪些其他选项?
答案 0 :(得分:5)
您的主要关注点似乎是隔离(为了安全性和稳健性)。
因此,您最好的选择是在单独的AppDomain中激活您的插件。在此域中,您可以控制允许加载的程序集(请参阅AppDomainSetup类)。
您的主代码也将受到保护,免受插件内发生的任何不良事件的影响:所有插件方法都必须使用核心对象的副本(除非您传递的对象继承自MarshalByRefObject,在这种情况下,所有赌注都是关闭)。 addin方法中的例外可以通过将所有调用包装在try除外,或通过AppDomain的UnhandledExcption事件来处理。
请记住,跨越AppDomain边界会有性能损失。这个电话基本上是一个远程呼叫。
另一个潜在的问题是您打算如何管理AppDomains。我从未试图在一个过程中创建多个AppDomain,但我希望在这里遇到麻烦。在单个域中为多个用户组合Addins将挑战您尝试构建的保护
回应@RationalGeek问题 - UnhandledException event允许这样做 - 有点儿。您可以在核心域和插件域中订阅此事件,但这样做有很多不确定性 - 请参阅我引用的文章以获取更多详细信息。可能更好的选择是在try / except
中包装对API的每次调用答案 1 :(得分:1)
您可以尝试使用AppDomains并处理未处理的异常。为避免appdomain崩溃,您必须处理AppDomain.UnhandledException
在上面的链接中,请注意以下声明
从.NET Framework 4开始,不会针对损坏进程状态的异常(例如堆栈溢出或访问冲突)引发此事件,除非事件处理程序是安全关键的并且具有HandleProcessCorruptedStateExceptionsAttribute属性的
因此您可能需要明确处理某些配置。
我已经阅读了很多问题,声称当未处理的异常发生在子域中的不同线程上时,会冒泡并关闭父域。如果是这样,那么将所有插件加载到一个单独的进程中,每个插件都有一个appdomain或者将插件加载到单独的进程中可能是可取的。
我也发现了以下问题,我相信你会发现非常有帮助的
答案 2 :(得分:-1)
为什么不在运行时使用反射并发现可用的插件? Assembly.LoadFile来获取程序集, GetExportedTypes来获取您的对象 使用Activator.CreateInstance
创建实例然后在try循环中运行插件以确保它不会影响系统。虽然您需要一些重要的架构来提供实际稳定性。
除非您有复杂的插件管理方案,否则请远离MEF。如果它只是允许用户使用他们自己的一些,只需使用反射。