2

我正在尝试为我们的应用程序实现一个插件系统,并且有一段时间获取动态加载的 SWF 文件,加载额外的 SWF 文件。

它是这样的:

  1. 主要应用程序外壳加载...
  2. ---------+ 应用程序加载...
  3. -----------------+插件

我没有问题让应用程序 #1 加载应用程序 #2

但是,尽我所能,我无法让应用程序 #2 加载和实例化 #3

我使用 ModuleManager 尝试了各种排列,但这是我得到的最接近的。当调用 onLoadComplete 方法时,我可以看到 SWF 已加载,但工厂始终返回 NULL。

有趣的是,当我在它自己的应用程序中提取它时,它工作正常。这个问题是由我从本身动态加载的 SWF 加载插件这一事实触发的。

我相信这是由于ApplicationDomain,但我无法做出正面或反面。我尝试指定currentDomainnew ApplicationDomain(Application.currentDomain)new ApplicationDomain()没有成功。

此外,重要的是要注意,我不能在任何一个应用程序中对 Foo 类进行硬引用,因为就其性质而言,我们不会提前知道它们将包含什么。

谷歌搜索,这似乎是一个众所周知的问题,但我还没有找到(明确的)解决方案。

.
.
.
assetModule = ModuleManager.getModule("Foo.swf");    
assetModule.addEventListener(ModuleEvent.READY, onLoadComplete );
assetModule.addEventListener(ModuleEvent.ERROR, onLoadError);
assetModule.load();
.
.
.
private var _pluginInstance:Plugin;

private function onLoadComplete( event:Event ):void
{
    trace("module loaded");

    _pluginInstance = assetModule.factory.create() as Plugin;
    if( _pluginInstance )
        _pluginInstance.startup();
    else 
        Alert.show("unable to instantiate module");
}

private function onLoadError( event:Event ):void
{
       Alert.show("error");
}

My Plugin looks like this:

package
{
    import mx.collections.ArrayCollection;
    import mx.modules.ModuleBase;

        public class Plugin extends ModuleBase

        public function startup():void
        {

        }
.
.
.
}

package 
{
    import Plugin;
    import mx.modules.ModuleBase;

    public class Foo extends Plugin
    {
        public function Foo()
        {
            trace("foo constructor invoked");
        }

        override public function startup():void
        {
                    trace("foo started");
        }
.
.
.
}
4

2 回答 2

0

如果你真的想在你的插件和你的应用程序之间使用一个通用的接口,你的应用程序的 Plugin 类必须和你的插件的 Plugin 类相同。为此,它们需要 b 在同一个 ApplicationDomain 中。

//In an external library
public interface Plugin {}

//In your application
_pluginInstance = assetModule.factory.create() as Plugin;
...


//In your plugin
public class MyPlugin implements Plugin

问题是,当你编译你的插件 swf 时,你也会编译 Plugin。这不是问题,但您需要告诉您的应用程序它与他的相同:

var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));    

ApplicationDomain.currentDomain 是这里的关键。如果您参考文档

Loader自己的ApplicationDomain。您在使用 ApplicationDomain.currentDomain 时使用此应用程序域。加载完成后,父子可以直接使用对方的类。如果子类试图定义一个与父类已经定义的类同名的类,则使用父类并忽略子类。

于 2009-07-04T21:42:38.370 回答
0

@joshtynjala 是对的。我发现尝试只使用 Object 然后在其上调用方法(不要强制转换)。

var MyPlugin : Object = getPlugin(); MyPlugin.doPluginFunc();

一般可以在 system/flex 类之间转换没问题。不知道将插件作为运行时库是否会有所帮助?

于 2009-06-03T17:42:33.677 回答