I'm trying to implement a plugin system for our application, and having a devil of a time getting SWF file which was dynamically loaded itself, load additional SWF files.
我正在尝试为我们的应用程序实现一个插件系统,并且有一段时间获得自动动态加载的SWF文件,加载其他SWF文件。
It goes something like this:
它是这样的:
- Main Application Shell loads...
- ---------+ Application loads...
- -----------------+Plugin(s)
主要应用Shell加载......
--------- +应用程序加载......
I have no problem getting app #1 to load app #2
我没有问题让app#1加载app#2
However, try as I might, I cannot get app #2 to load and instantiate #3
但是,尽我所能,我无法获得app#2来加载和实例化#3
I've tried various permutations using the ModuleManager, but this is the closest I get. When the onLoadComplete method get invoked, I can see that the SWF loaded, however the factory always returns NULL.
我已经使用ModuleManager尝试了各种排列,但这是我得到的最接近的排列。调用onLoadComplete方法时,我可以看到SWF已加载,但工厂始终返回NULL。
What is interesting is that when I extract this out in its own application, it works fine. This issue is triggered by the fact that I'm loading Plugin from a SWF that was loaded dynamically itself.
有趣的是,当我在自己的应用程序中提取它时,它工作正常。这个问题是由我从一个动态加载的SWF加载插件这一事实引发的。
I believe this is due to the ApplicationDomain
, but I cannot make heads or tails of it. I tried specifying currentDomain
, new ApplicationDomain(Application.currentDomain)
and new ApplicationDomain()
without success.
我相信这是由于ApplicationDomain,但我无法做出正面或反面。我尝试指定currentDomain,new ApplicationDomain(Application.currentDomain)和new ApplicationDomain()但没有成功。
Also, it is important to note that I cannot make reference a hard reference to the Foo class in either applications since by their nature, we will not know ahead of time what they will contain.
此外,重要的是要注意,我不能在任何一个应用程序中引用Foo类的硬引用,因为从它们的性质来看,我们不会提前知道它们将包含什么。
Googlin' around, this seems to be a fairly known problem, but I have not found a (clear) solution yet.
Googlin',这似乎是一个相当已知的问题,但我还没有找到(明确的)解决方案。
.
.
.
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
{
}
.
.
.
}
and
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");
}
.
.
.
}
2 个解决方案
#1
@ joshtynjala is right. I found try just using Object then calling methods on it (don't cast).
@joshtynjala是对的。我发现尝试只使用Object然后调用它的方法(不要强制转换)。
var MyPlugin : Object = getPlugin(); MyPlugin.doPluginFunc();
var MyPlugin:Object = getPlugin(); MyPlugin.doPluginFunc();
Generally can cast between system/flex classes no problem. Don't know if putting Plugin as a runtime library would help ?
一般可以在系统/ flex类之间转换没问题。不知道将Plugin作为运行时库放置会有所帮助吗?
#2
If you really want to use a common interface between your plugin and your application, your application's Plugin class must be the same as your plugin's Plugin class. To do so, they need b to be in the same ApplicationDomain.
如果您真的想在插件和应用程序之间使用通用接口,那么您的应用程序的插件类必须与插件的插件类相同。为此,他们需要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
The problem is, when you will compile your plugin swf, you will also compile Plugin. This is not a problem, but you need to tell your application that it's the same as his :
问题是,当你编译你的插件swf时,你也会编译插件。这不是问题,但您需要告诉您的应用程序它与他的相同:
var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));
ApplicationDomain.currentDomain is the key here. If you refer to the docs :
ApplicationDomain.currentDomain是这里的关键。如果您参考文档:
Loader's own ApplicationDomain. You use this application domain when using ApplicationDomain.currentDomain. When the load is complete, parent and child can use each other's classes directly. If the child attempts to define a class with the same name as a class already defined by the parent, the parent class is used and the child class is ignored.
Loader自己的ApplicationDomain。使用ApplicationDomain.currentDomain时使用此应用程序域。加载完成后,父级和子级可以直接使用彼此的类。如果子项尝试定义与父项已定义的类名相同的类,则使用父类,并忽略子类。
#1
@ joshtynjala is right. I found try just using Object then calling methods on it (don't cast).
@joshtynjala是对的。我发现尝试只使用Object然后调用它的方法(不要强制转换)。
var MyPlugin : Object = getPlugin(); MyPlugin.doPluginFunc();
var MyPlugin:Object = getPlugin(); MyPlugin.doPluginFunc();
Generally can cast between system/flex classes no problem. Don't know if putting Plugin as a runtime library would help ?
一般可以在系统/ flex类之间转换没问题。不知道将Plugin作为运行时库放置会有所帮助吗?
#2
If you really want to use a common interface between your plugin and your application, your application's Plugin class must be the same as your plugin's Plugin class. To do so, they need b to be in the same ApplicationDomain.
如果您真的想在插件和应用程序之间使用通用接口,那么您的应用程序的插件类必须与插件的插件类相同。为此,他们需要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
The problem is, when you will compile your plugin swf, you will also compile Plugin. This is not a problem, but you need to tell your application that it's the same as his :
问题是,当你编译你的插件swf时,你也会编译插件。这不是问题,但您需要告诉您的应用程序它与他的相同:
var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));
ApplicationDomain.currentDomain is the key here. If you refer to the docs :
ApplicationDomain.currentDomain是这里的关键。如果您参考文档:
Loader's own ApplicationDomain. You use this application domain when using ApplicationDomain.currentDomain. When the load is complete, parent and child can use each other's classes directly. If the child attempts to define a class with the same name as a class already defined by the parent, the parent class is used and the child class is ignored.
Loader自己的ApplicationDomain。使用ApplicationDomain.currentDomain时使用此应用程序域。加载完成后,父级和子级可以直接使用彼此的类。如果子项尝试定义与父项已定义的类名相同的类,则使用父类,并忽略子类。