3

バックグラウンド

純粋な Action Script 3 で高度にモジュール化されたアプリケーションを開発しています (ビルドを自動化するために Flex 4 SDK を使用していますが、すべてのコードは Flash CS4 Professional で直接コンパイルできる必要があります)。

すべてのモジュール間で共有されるインターフェース定義を含む「framework.swc」ファイル、他のモジュールをロードする「mainmodule.swf」、そして他のモジュール用のさまざまな .swf ファイルがあります。クラスを動的にロードするために ApplicationDomain::getDefinition() と組み合わせて Loader クラスを使用しています ["new LoaderContext(false,ApplicationDomain.currentDomain)" を使用します]。

問題

すべてのモジュールは、「framework.swc」で定義されている「AbstractModule」インターフェースを実装しています。ただし、動的にロードされたモジュールをインスタンス化すると (module is AbstractModule) は false を返します。さらに重要なことは、someobject が「framework.swc」で定義されたインターフェイスを実装し、モジュールのメソッドが「framework.swc」で定義された同じインターフェイスのオブジェクトを期待している場合に、module.someMethod(someobject) を呼び出すと、ランタイム エラーが発生することです。 「TypeError: エラー #1034: 型強制に失敗しました: _ を _ に変換できません。」

"mainmodule.swf" と "loadedmodule.swf" (テスト用にロードしたモジュール) は、内部的に、"framework.swc" の共有インターフェイスに別々の定義を使用しているようです。

質問

「mainmodule.swf」と「loadedmodule.swf」が共通のインターフェースを共有定義に解決して、クラスのキャストとクラスの比較が正しく成功するようにするにはどうすればよいですか?

4

4 に答える 4

1

Ok。これは最も美しい解決策ではありませんが、うまくいきます。基本的に、すべてのインターフェイス "AbstractX" ("X" を別のものに置き換えます) に対して、"ImportX" と "ExportX" の 2 つのラッパー クラスを作成する必要があります。ExportX の目標は、AbstractX をラップすることによって、AbstractX を Object 型に正常に拡張し、AbstractX 型と同じメソッドをすべて提供することですが、組み込み/定義済みのデータ型またはシグネチャのフラッシュの一部であるデータ型のみを使用することです。ImportX の目的は、AbstractX 型と同じ特性 (ただし、AbstractX 型にキャストできず、AbstractX 型として認識されない) で動的に読み込まれるオブジェクトを、AbstractX インターフェイスの Object 型に絞り込むことです。ExportX と ImportX はどちらも ImportY、ImportZ などを使用します。ただし、ExportX は ImportY、ImportZ などを使用します。パラメーターをラップして、AbstractX 型のオブジェクトに委譲する一方で、ImportX はそれらを使用して、Object 型のオブジェクトに委譲することから生じる戻り値をラップします。これをもう少しわかりやすくするために、次の例を示します。

パブリック インターフェイス AbstractX
{
    // export/import 関数は必須です
    // そのようなすべてのインターフェース。彼らは許可します
    // ラッパーが正しく操作されるようにします。
    関数 export() : オブジェクト;
    関数 original() : オブジェクト;

    // インターフェイス関数は次のように異なります
    // インターフェイスからインターフェイスへ。彼らはできる
    // より適切な呼び方。
    関数 interfaceFunction1(param : AbstractY) : AbstractZ;
    関数 interfaceFunction2(param : AbstractA) : AbstractB;
}
// Import_ 型のクラスは常に Abstract_ を実装します
public クラス ImportX は AbstractX を実装します
{
    // Import_ Object のコンストラクタ
    // 常に Object 型です。
    public function ImportX(obj : Object) : void {
        _loadedobj = obj;
        _exportobj = obj.export();
    }

    // すべての Import_ クラスは、同様の「ラップ」関数を実装する必要があります:
    public static function wrap(obj : Object) : AbstractX {
        var 結果: AbstractX = null;
        if ( obj != null ){
            if ( obj is AbstractX ){ // 変換可能な場合は直接ラップしないでください。
                結果 = obj as AbstractX;
            }else if ( obj.original() is AbstractX ){ // 二重ラップしない
                結果 = obj.original() as AbstractX;
            }そうしないと{
                // ラップする必要があります。
                結果 = 新しい ImportX(obj);
            }
         }
         結果を返します。
     }

    public function export() : オブジェクト {
        _exportobj を返します。
    }

    public function original() : オブジェクト {
        _loadedobj を返します。
    }

    // インターフェイス関数については、_exportobj に委譲します
    // 戻り値をラップしますが、パラメーターはラップしません。
    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 : オブジェクト;
    private var _exportobj : オブジェクト;
}
// Export_ オブジェクトは Abstract_ 型と同様のメソッドを提供しますが、
// シグニチャを変更して、組み込み/定義済みの型のみを使用できるようにする必要があります
// 現れる。したがって、Export_ は Abstract_ を実装しません。
パブリック クラス ExportX
{
    // Export_ のコンストラクタは、常に Abstract_ 型のオブジェクトを取ります
    public function ExportX(obj : AbstractX) : void {
        _obj = obj;
    }

    public function original() : オブジェクト {
        _obj を返します。
    }

    public function export() : オブジェクト {
        これを返します。
    }

    // インターフェイス関数については、_obj にデリゲートします
    // 戻り値ではなく、パラメータをラップします。
    // 署名の変更にも注意してください。
    public function interfaceFunction1(param : Object) : オブジェクト {
        return _obj.interfaceFunction1(AbstractY.wrap(param));
    }

    public function interfaceFunction2(param : Object) : オブジェクト {
        return _obj.interfaceFunction2(AbstractA.wrap(param));
    }

    プライベート var _obj : AbstractX = null;
}
// クラス X の定義は、任意のモジュールで発生し、ロードされる可能性があります。
public class X は AbstractX を実装します
{
    public function X( /* ... */ ) : void {
        //...
    }

    public function export() : オブジェクト {
        if ( ! _export ){
            _export = 新しい ExportX(これ);
        }
        _エクスポートを返します。
    }

    public function original() : オブジェクト {
        これを返します。
    }

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

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

    プライベート var _export : オブジェクト = null;
}
// Ok。では、これをどう使うかというと…
var classx : Class = dynamicLoadClassFromModule("X","module.swf");
var untypedx : Object = new classx();
var typedx : AbstractX = ImportX.wrap(untypedx);
// typedx を使用 ...
于 2009-07-19T03:09:54.620 に答える
0

必要なものかどうかは 100%わかりませんが、 Gaia Frameworkはグローバル API を実装しており、多くの swfs が相互にやり取りするために共有しています。あなたはそれをチェックして、おそらくいくつかのアイデアを得ることができます. 現在、私はあなたと非常によく似た状況に直面しているので、代替手段を確認しています...この投稿は非常に役立ちます。ありがとう!

于 2009-07-20T11:42:41.047 に答える
0

ここ-compiler.external-library-pathに記載されているように試してください...そのようにして、インターフェースに依存する1つのswcを構築できます。それはそこにはありませんが、別のインターフェースから来ているため、衝突を回避できます... CS4でそれを行う方法がわかりませんけれど ...

挨拶

back2dos

于 2009-07-11T01:58:33.993 に答える