Как заставить класс Action Script 3, используемый в двух SWF-файлах, преобразоваться в один и тот же класс, когда один SWF-файл динамически загружает другой? - PullRequest
3 голосов
/ 11 июля 2009

Фон

Я разрабатываю высокомодульное приложение на чистом Action Script 3 (мы используем Flex 4 SDK для автоматизации наших сборок, но весь наш код должен быть в состоянии компилироваться непосредственно во Flash CS4 Professional).

У нас есть файл "framework.swc", который содержит определения интерфейсов, которые являются общими для всех наших модулей, у нас есть "mainmodule.swf", который загружает наши другие модули, а затем у нас есть различные файлы .swf для других наших модулей. , Мы используем класс Loader в сочетании с ApplicationDomain :: getDefinition () для динамической загрузки классов [мы используем «новый LoaderContext (false, ApplicationDomain.currentDomain)»].

Задача

Все наши модули реализуют интерфейс «AbstractModule», который определен в «framework.swc». Однако, когда я создаю экземпляр динамически загруженного модуля (модуль является AbstractModule), возвращается false. Что еще более важно, если я вызываю module.someMethod (someobject), где someobject реализует интерфейс, определенный в "framework.swc", и где метод модуля ожидает объект того же интерфейса, определенного в "framework.swc", я получаю ошибку во время выполнения «Ошибка типа: ошибка № 1034: сбой приведения типа: невозможно преобразовать _ в _».

Похоже, что "mainmodule.swf" и "loadedmodule.swf "(модуль, который я загружаю для тестирования) внутренне используют отдельные определения для общих интерфейсов в" framework.swc "

Вопрос

Как я могу заставить "mainmodule.swf" и "loadedmodule.swf "разрешить их общие интерфейсы в общее определение, чтобы преобразование классов и сравнение классов проходили правильно?

Ответы [ 4 ]

1 голос
/ 19 июля 2009

Хорошо. Это не самое красивое решение, но оно будет работать. По сути, для каждого интерфейса «AbstractX» (замените «X» чем-то другим) вам нужно создать два класса-обертки: «ImportX» и «ExportX». Цель ExportX состоит в том, чтобы успешно расширить AbstractX до типа Object, оборачивая AbstractX, предоставляя все те же методы, что и тип AbstractX, но используя только встроенные / предопределенные типы данных или типы данных, которые являются частью flash в их сигнатурах. Цель ImportX состоит в том, чтобы сузить динамически загружаемый объект с теми же характеристиками, что и тип AbstractX (но который не может быть приведен к типу AbstractX и который не распознается как тип AbstractX), но имеет тип Object для интерфейса AbstractX. И ExportX, и ImportX используют ImportY, ImportZ и т. Д .; однако ExportX использует ImportY, ImportZ и т. д. для переноса параметров, которые он делегирует объекту типа AbstractX, в то время как ImportX использует их для переноса возвращаемых значений, которые возникают при делегировании объекту типа Object. Чтобы сделать это немного более понятным, я привожу следующие примеры:

public interface AbstractX
{
    // The export/import functions are mandatory 
    // for all such interfaces. They allow
    // for the wrappers to be correctly manipulated.
    function export() : Object;
    function original() : Object;

    // The interface functions vary from 
    // interface to interface. They can
    // be called something much more appropriate.
    function interfaceFunction1(param : AbstractY) : AbstractZ;
    function interfaceFunction2(param : AbstractA) : AbstractB;
}
// A class of type Import_ always implements Abstract_
public class ImportX implements AbstractX
{
    // The constructor for an Import_ Object
    // is always of type Object.
    public function ImportX(obj : Object) : void {
        _loadedobj = obj;
        _exportobj = obj.export();
    }

    // Every Import_ class must implement a similar "wrap" function:
    public static function wrap(obj : Object) : AbstractX {
        var result : AbstractX = null; 
        if ( obj != null ){
            if ( obj is AbstractX ){ // Don't wrap if convertible, directly.
                result = obj as AbstractX;
            }else if ( obj.original() is AbstractX ){ // Don't double wrap
                result = obj.original() as AbstractX;
            }else{
                // Needs to be wrapped.
                result = new ImportX(obj);
            }
         }
         return result;
     }

    public function export() : Object {
        return _exportobj;
    }

    public function original() : Object {
        return _loadedobj;
    }

    // For the interface functions, we delegate to _exportobj
    // and we wrap the return values, but not the parameters.
    public function interfaceFunction1(param : AbstractY) : AbstractZ {
        return AbstractZ.wrap(_exportobj.interfaceFunction1(param));
    }

    public function interfaceFunction2(param : AbstractA) : AbstractB {
        return AbstractB.wrap(_exportobj.interfaceFunction2(param));
    }

    private var _loadedobj : Object;
    private var _exportobj : Object;
}
// Although an Export_ object provides SIMILAR methods to type Abstract_,
// the signatures need to be changed so that only builtin/predefined types
// appear. Thus Export_ NEVER implements Abstract_.
public class ExportX
{
    // The constructor to Export_ always takes an object of type Abstract_
    public function ExportX(obj : AbstractX) : void {
        _obj = obj;
    }

    public function original() : Object {
        return _obj;
    }

    public function export() : Object {
        return this;
    }

    // For the interface functions, we delegate to _obj
    // and we wrap the parameters, not the return values.
    // Also note the change in signature.
    public function interfaceFunction1(param : Object) : Object {
        return _obj.interfaceFunction1(AbstractY.wrap(param));
    }

    public function interfaceFunction2(param : Object) : Object {
        return _obj.interfaceFunction2(AbstractA.wrap(param));
    }

    private var _obj : AbstractX = null;
}
// The definition of class X can occur in and be loaded by any module.
public class X implements AbstractX
{
    public function X( /* ... */ ) : void {
        //...
    }

    public function export() : Object {
        if ( ! _export ){
            _export = new ExportX(this);
        }
        return _export;
    }

    public function original() : Object {
        return this;
    }

    public function interfaceFunction1(param : AbstractY) : AbstractZ {
        // ...
    }

    public function interfaceFunction2(param : AbstractA) : AbstractB {
       // ...
    }

    private var _export : Object = null;
}
// Ok. So here is how you use this...
var classx   : Class = dynamicallyLoadClassFromModule("X","module.swf"); 
var untypedx : Object = new classx();
var typedx   : AbstractX = ImportX.wrap(untypedx);
// Use typedx ...
0 голосов
/ 20 июля 2009

Я не уверен на 100%, если это то, что вам нужно, но Gaia Framework реализует глобальный API, совместно используемый многими SWF для взаимодействия друг с другом. Вы можете проверить это и, возможно, получить некоторые идеи. Прямо сейчас я сталкиваюсь с довольно похожей ситуацией, как у вас, поэтому я проверяю альтернативы ... этот пост будет очень полезен, спасибо!

0 голосов
/ 11 июля 2009

Возможно, вы захотите использовать совместно используемую библиотеку времени выполнения (RSL). RSL позволяет вам выполнять динамическое связывание. Однако я не знаю, сможет ли CS4 их построить. Возможно, вы могли бы пересмотреть требование «должен быть в состоянии скомпилировать непосредственно во Flash CS4» или изучить компиляцию с помощью Flex SDK с помощью макросов / сценариев в IDE CS4.

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

0 голосов
/ 11 июля 2009

вы должны попробовать -compiler.external-library-path как задокументировано здесь ... таким образом, вы можете создать один SWC, имеющий зависимости от интерфейса, который не находится в нем, но поступает от другого, что позволяет избежать коллизий. .. не знаю, как это сделать в CS4, хотя ...

Greetz

back2dos

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...