代码之家  ›  专栏  ›  技术社区  ›  Michael Aaron Safyan

当一个SWF动态加载另一个SWF时,如何使两个SWF文件中使用的ActionScript3类解析为同一个类?

  •  3
  • Michael Aaron Safyan  · 技术社区  · 17 年前

    我正在用纯动作脚本3开发一个高度模块化的应用程序(我们使用Flex4SDK来自动化构建,但我们所有的代码都必须能够直接在FlashCS4Professional中编译)。

    我们有一个“framework.swc”文件,其中包含在所有模块之间共享的接口定义,我们有一个“mainmodule.swf”加载其他模块,然后我们有其他模块的各种.swf文件。我们正在使用Loader类,与ApplicationDomain::getDefinition()一起动态加载类[我们使用“new LoaderContext(false,ApplicationDomain.currentDomain)”]。

    问题

    我们的所有模块都实现“AbstractModule”接口,该接口在“framework.swc”中定义。然而,当我实例化一个动态加载的模块时,(模块是AbstractModule)返回false。更重要的是,如果我调用module.someMethod(someobject),其中someobject实现了在“framework.swc”中定义的接口,并且模块的方法需要一个与在“framework.swc”中定义的接口相同的对象,那么我会得到一个运行时错误“TypeError:error#1034:类型强制失败:无法转换为”

    似乎“mainmodule.swf”和“loadedmodule.swf”(我一直在加载用于测试的模块)在内部对“framework.swc”中的共享接口使用单独的定义

    如何使“mainmodule.swf”和“loademdodule.swf”将它们的公共接口解析为共享定义,以便正确地进行类转换和类比较?

    4 回复  |  直到 17 年前
        1
  •  1
  •   Michael Aaron Safyan    17 年前

    好啊这不是最漂亮的解决方案,但它会起作用。基本上,对于每个接口“AbstractX”(用其他东西替换“X”),您需要创建两个包装器类:“ImportX”和“ExportX”。ExportX的目标是通过包装一个AbstractX,成功地将AbstractX扩展到type对象,提供与type AbstractX相同的所有方法,但只使用内置/预定义数据类型或在签名中作为flash一部分的数据类型。ImportX的目标是缩小动态加载的对象的范围,该对象具有与类型AbstractX相同的特性(但不能转换为类型AbstractX,也不能识别为类型AbstractX),但属于AbstractX接口的类型object。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 ...
    
        2
  •  0
  •   back2dos    17 年前

    你应该试试 -compiler.external-library-path here ... 这样,您可以构建一个依赖于某个接口的swc,该接口不在其中,而是来自另一个接口,从而避免冲突。。。我不知道如何在CS4中做到这一点。。。

    尔兹

    back2dos

        3
  •  0
  •   Jacob    17 年前

    您可能希望使用运行时共享库(RSL)。RSL允许您进行动态链接。然而,我不知道CS4是否可以构建这些。也许您可以重新考虑“必须能够在FlashCS4中直接编译”的要求,或者考虑通过CS4IDE中的宏/脚本使用FlexSDK进行编译。

        4
  •  0
  •   Cay    17 年前

    我不是100%确定这是否是你需要的,但是 Gaia Framework

    推荐文章