Создание подключаемых модулей в Flex - загрузка вложенных файлов SWF

Asked
Viewd1402

2

Я пытаюсь реализовать систему плагинов для нашего приложения и, черт возьми, получаю SWF-файл, который сам динамически загружается, загружаю дополнительные SWF-файлы.

Это выглядит примерно так:

  1. Основная оболочка приложения загружается ...
  2. --------- + Приложение загружается ...
  3. ----------------- + Плагин (ы)

У меня нет проблем с загрузкой приложения №1 для загрузки приложения №2

Однако, как бы я ни старался, я не могу заставить приложение №2 загрузить и создать экземпляр №3

Я пробовал различные перестановки с помощью ModuleManager, но это самый близкий мне вариант. Когда вызывается метод onLoadComplete, я вижу, что SWF загружен, однако фабрика всегда возвращает NULL.

Что интересно, когда я извлекаю это в собственном приложении, он работает нормально. Эта проблема вызвана тем фактом, что я загружаю подключаемый модуль из SWF, который сам загружался динамически.

Я полагаю, что это связано с ApplicationDomain, но я не могу разобраться в этом. Я безуспешно пытался указать currentDomain, new 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");
        }
.
.
.
}
 
  • Я давно не работал с доменами приложений, поэтому не могу дать исчерпывающий ответ на ваш вопрос, но могу сказать вам, что проблема здесь:

    assetModule.factory.create () как плагин;

    Класс плагина в вашем модуле и класс плагина в вашем основном приложении не совпадают с точки зрения виртуальной машины. Приведение с использованием «как плагин» возвращает null, потому что Plugin! = Plugin. Я не могу вспомнить, как это обойти (кроме преобразования в Object или что-то в этом роде), но вы на правильном пути, исследуя класс ApplicationDomain.

    Josh Tynjala29 апреля 2009, 22:15

2 ответов

0

Если вы действительно хотите использовать общий интерфейс между вашим плагином и приложением, класс плагина вашего приложения должен быть таким же, как класс плагина вашего плагина. Для этого они должны 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 своего плагина, вы также скомпилируете плагин. Это не проблема, но вы должны сообщить своему приложению, что оно такое же, как и его:

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

ApplicationDomain.currentDomain является здесь ключевым. Если вы обратитесь к документам :

Собственный ApplicationDomain загрузчика. Вы используйте этот домен приложения при использовании ApplicationDomain.currentDomain. когда загрузка завершена, родитель и ребенок могут напрямую использовать классы друг друга. Если ребенок пытается определить класс с тем же именем, что и класс уже определено родителем, родительский класс используется, а дочерний класс игнорируется.

0

@ joshtynjala права. Я обнаружил, что попробуйте просто использовать Object, а затем вызвать на нем методы (не приводить).

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

Как правило, можно без проблем переходить между классами system / flex. Не знаете, поможет ли размещение плагина в качестве библиотеки времени выполнения?