flashairflex3dynamic-loadingplugin-architecture

Building a Plugin Architecture with Adobe AIR


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?


Solution

  • 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 the mx.modules package.) The gist of it is that you subclass plugins from ModuleBase and use ModuleManager 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:

    "By default, a module is loaded into a child domain of the current application domain. You can specify a different application domain by using the applicationDomain property of the ModuleLoader class."

    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.