我正在考虑选择 Adobe AIR 作为即将进行的项目的客户端实施技术。 (之前的选择是 C# 和 WPF,但最近 Flash/Flex/AIR 给我留下了深刻的印象。)
但是我的产品最重要的功能之一将是它的插件架构,允许第三方开发人员扩展功能和GUI 以有趣的方式。
我知道如何用 C# 设计架构:插件加载器将枚举本地“app/plugins/”目录中的所有程序集。 对于每个程序集,它会枚举所有类,寻找“IPluginFactory”接口的实现。 对于工厂创建的每个插件,我会询问其 MVC 类,并将其 GUI 元素(菜单项、面板等)插入现有 GUI 布局中的适当插槽中。
我想在 AIR 中完成同样的事情(从本地文件系统加载插件,而不是从网络加载插件)。 阅读这篇文章后,我的理解是这是可能的,并且基本架构(将 SWF 加载到沙盒应用程序域等)与在 .NET 中执行此操作的方式非常相似。
但我对其中的陷阱很好奇。
如果你们中的任何人使用 Flash 播放器(最好是在混合 Flash/Flex 应用程序中,特别是在 AIR 主机中)完成了任何动态类加载,我很想听听您构建插件框架的经验以及遇到棘手情况的情况使用 flash 播放器以及 flash、flex 和 AIR API。
例如,如果有人问我同样的问题,但考虑到 Java 平台,我肯定会提到 JVM 没有“模块”或“程序集”的概念。 聚合的最高级别是“类”,因此在插件系统中创建组织结构来管理大型项目可能很困难。 我还将讨论多个类加载器的问题,以及每个类加载器如何维护自己单独的加载类实例(具有自己单独的静态变量)。
以下是一些尚未解答的具体问题:
1) 动作脚本“Loader”类可以将 SWF 加载到 ApplicationDomain 中。 但该应用程序域到底包含什么? 模块? 上课? MXML 组件是如何表示的? 如何找到实现我的插件接口的所有类?
2)如果您已将插件加载到与主应用程序不同的应用程序域中,那么从其他应用程序域中调用代码是否会更加复杂? 对于可以通过应用程序域间编组层的数据类型是否有任何重要限制? 编组费用是否过高?
3)理想情况下,我希望将自己的大部分主要代码开发为插件(主应用程序只不过是插件加载外壳),并使用插件架构将该功能提升到应用程序中。 这是否让你内心感到恐惧?
I'm thinking of choosing Adobe AIR as the client-side implementation technology for an upcoming project. (The previous choice was C# and WPF, but I've been really impressed with Flash/Flex/AIR lately.)
But one of the most important features of my product will be its plugin architecture, allowing third party developers to extend the functionality and GUI in interesting ways.
I know how I'd design the architecture in C#: A plug-in loader would enumerate all of the assemblies in the local "app/plugins/" directory. For each assembly, it'd enumerate all of the classes, looking for implementations of the "IPluginFactory" interface. For each plugin created by the factory, I'd ask it for its MVC classes, and snap its GUI elements (menu items, panels, etc) into the appropriate slots in the existing GUI layout.
I'd like to accomplish the same thing within AIR (loading plugins from the local filesystem, not from the web). After reading this article, my understanding is that it's possible, and that the basic architecture (loading SWFs into sandboxed ApplicationDomains, etc) is very similar to the way you'd do it in .NET.
But I'm curious about the gotchas.
If any of you have done any dynamic classloading with the flash player (preferably in mixed flash/flex apps, and ESPECIALLY within the AIR host), I'd love to hear about your experiences building your plugin framework and where you ran into tricky situations with the flash player, and with the flash, flex, and AIR APIs.
For example, if someone asked me this same question, but with the Java platform in mind, I'd definitely mention that the JVM has no notion of "modules" or "assemblies". The highest level of aggregation is the "class", so it can be difficult to create organizational structures within a plugin system for managing large projects. I'd also talk about issues with multiple classloaders and how each maintains its own separate instance of a loaded class (with its own separate static vars).
Here are a few specific questions still unanswered for me:
1) The actionscript "Loader" class can load an SWF into an ApplicationDomain. But what exactly does that appdomain contain? Modules? Classes? How are MXML components represented? How do I find all of the classes that implement my plugin interface?
2) If you've loaded a plugin into a separate ApplicationDomain from the main application, is it substantially more complicated to call code from within that other appdomain? Are there any important limitations about the kinds of data that can pass through the inter-appdomain marshalling layer? Is marshalling prohibitively expensive?
3) Ideally, I'd like to develop the majority of my own main code as a plugin (with the main application being little more than a plugin-loading shell) and use the plugin architecture to hoist that functionality into the app. Does that strike fear in your heart?
发布评论
评论(4)
不幸的是,您无法枚举给定域中的类(好吧,至少我不知道有什么方法可以做到这一点),但常见的解决方案是要求(如“插件接口”中)存在一个众所周知的类每个 swf 中的工厂,它将返回插件的定义(类)或插件本身。
顺便说一句,Flash Player也有安全域的概念,但我实际上从未接触过它,所以我不知道这里有什么可能性。
Unfortunately you cannot enumerate the classes in a given domain (well, at least I don't know any way to do it), but the common solution is to require (as in "The Plugin Interface") the presence of a well-known factory in each swf, which will return either the definition (Class) of the plugin or the plugin itself.
Btw, Flash Player also a concept of security domain, but I actually never touched it, so I don't known what the possibilities are here.
Luca Tettamanti 已经对您的具体问题给出了很好的答案,因此我将仅提供一些有关一般主题的附加信息:
我使用
ModuleManager
类(以及mx.modules
包。)其要点是,您从ModuleBase
中继承插件,并在主机应用程序中使用ModuleManager
来加载它们。 然后你让插件实现一个通用接口(例如IMyAppPlugin
)并使用某种facade 来表示和实现插件可以使用的主机应用程序的接口(例如,MyAppFacade 实现 IMyAppFacade
。)每当加载插件时,都会将此 Facade 引用注入其中。主题“模块化应用程序概述” Flex 3 帮助中有一些很好的信息(子章节“模块域”讨论了模块上下文中的应用程序域。)以下是摘录:
主题 “使用 ApplicationDomain 类” 更深入地讨论了应用程序域的主题,如果您还没有阅读过,您一定应该阅读它。
Luca Tettamanti gave good answers to your specific questions already, so I'll just offer some additional info on the general subject:
I've implemented a simple plugin API for a Flex app using the
ModuleManager
class (and the other stuff in themx.modules
package.) The gist of it is that you subclass plugins fromModuleBase
and useModuleManager
in the host app to load them. Then you have the plugins implement a common interface (e.g.IMyAppPlugin
) and use some sort of a facade to represent and implement the interface to the host application that the plugins can use (e.g.MyAppFacade implements IMyAppFacade
.) Whenever plugins are loaded, inject this facade reference into them.The topic "Modular applications overview" in the Flex 3 help has some good info (the subchapter "Module domains" discusses application domains in the context of modules.) Here's an excerpt:
The topic "Using the ApplicationDomain class" goes into more depth on the subject of application domains, and you should definitely read it if you haven't already.
您是否尝试过加载子应用程序?
有关于在 AIR 中执行此操作的良好文档,我在几个小时内就成功完成了。 然而,由于子应用程序和主应用程序之间的沙箱冲突,相同的实现在 Flex 中却是不同的情况。 我花了好几个星期把头撞到墙上。
Have you tried loading sub-applications ?
There is good documentation for doing this in AIR and I was successful with it in a few hours. However, the same implementation is a different story in Flex because of sandbox violation between sub-application and main application. I have spend weeks pounding my head into the wall.
回应有关 Java 作为可能的插件架构的说法:
事实证明,Java 多年来一直被用来设计插件架构系统。 至于客户端,Equinox OSGi 模块管理框架可能是最知名的。 Eclipse IDE 有一次在 Equinox OSGi 之上重构了其插件架构。 从历史悠久的历史以及广泛的用户群和插件开发的后续社区来看,Eclipse IDE 可能是迄今为止最成功的客户端插件架构系统之一。 他们还提供插件架构作为设计任意客户端应用程序的基础框架 - Eclipse RCP。
我不得不插入这一点,因为虽然 Java 被定位为可能是一个非常弱的选择,但实际上它在交付此类工作系统方面比迄今为止的任何其他语言/运行时环境都要成功得多 - 特别是与 C# .NET 相比,当然,它具有良好的模块固有功能。 有点讽刺,但你已经明白了。
至于 Adobe AIR,我正在开发管理一个在 AIR 上设计的项目。 在我们的例子中,我们的模块可扩展性始终从 Web 服务器提供 - 而不是本地目录。 Flex 具有
标签,用于创建可在运行时离散加载的模块。
遗憾的是,AIR 的一个缺点是它缺乏用于启动其他应用程序的任何类 API。 您可以加载 URL 以在用户的默认浏览器中加载某些内容,但无法启动 Excel 等程序。 Java 和 C# 都有用于将其他应用程序作为外部进程启动的 API。
Responding to the statement regarding Java as a possible plug-in architecture:
It turns out Java has been used to devise plug-in architecture systems for many years. As to to client-side, the Equinox OSGi module management frameworks is probably the best well known. At one point the Eclipse IDE refactored their plug-in architecture on top of Equinox OSGi. Eclipse IDE is perhaps one of the most successful client-side plug-in architecture systems yet devised - from historical longevity point of view as well as breadth of user base and follow-on community of plug-in development. They also offer their plugin architecture as a foundational framework for devising arbitrary client-side applications - Eclipse RCP.
I just had to interject this because though Java was positioned as perhaps a very weak choice for this, it actually is far more successful than any other language/runtime environment to date in delivering working systems of this kind - especially vs. C# .NET, which, of course, has good innate facility for modules. Is kind of ironic, but there you have it.
As to Adobe AIR, I'm dev managing a project this is being devised on AIR. In our case our module extensibility is always going to be delivered from the web server - not a local directory. Flex has the
<mx:Module/>
tag for creating modules that can be loaded discretely at runtime.
Alas, a frustration with AIR is its lack of any class APIs for launching other applications. You can load a URL to load something in the user's default browser, but you can't launch, say, Excel. Both Java and C# have APIs for launching other apps as external processes.