1

Rather than use a hard-coded switch statement where you pass it the string name of a class and it then instantiates the appropriate class, I'd like to pass the actual name of the class to my factory method and have it dynamically create an instance of that class. I thought it would be trivial and am surprised it is not working. I must be missing something quite basic:

sample code:

createProduct(50, "Product1Class");
createProduct(5, "Product2Class");


private function createProduct(amount:uint, productClassName:String):void {
    var productReference:Class;
    try {
        productReference = getDefinitionByName(productClassName) as Class;

        for (var i:uint = 0; i < amount; i++) {
        var product = new productReference() as ProductBaseClass; // throws reference error!
        }
    } catch (error:ReferenceError) {
        throw new ReferenceError(error.message + " Have you linked a library item to this class?");
    }
 }

The only thing that may be a little odd (not sure) is that these "products" are actually linked Library items (ie: I have a movieClip in the Library that has a linkage to Product1Class and another to Product2Class both of which extend ProductBaseClass, which in turn extends MovieClip.

Why the ReferenceError?

4

3 に答える 3

1

getDefinitionByName()およびApplicationDomain.currentDomain.hasDefinition()には、完全修飾クラス名が必要です。元の投稿のサンプルコードは、Product1ClassとProduct2Classがデフォルトのパッケージに含まれている場合に機能します。ただし、製品クラスを別のパッケージに移動する場合は、getDefinitionByName()に完全修飾クラス名を指定していることを確認する必要があります。

したがって、製品クラスをcom.example.productsに配置すると、呼び出しは次のようになります。

productReference = getDefinitionByName("com.example.products.Product1Class") as Class;

この種の動的ファクトリクラスのベストプラクティスはよくわかりませんが、(すべての製品が同じパッケージに含まれていたため)最終的には、ファクトリクラス内に自分のパッケージを定義する定数を作成することになりました。製品:

private const PRODUCT_PACKAGE:String = "com.example.products."; // note the trailing period

そのため、クライアントコードは製品パッケージを知る(定義する)必要がありません。getDefinitionByName()を使用するときは、この定数を製品クラス名の前に追加するだけです。

于 2011-01-09T03:17:08.267 に答える
1

If you have a runtime loaded library then the Class's are not compiled into the main swf, so you get the runtime reference error when you try to create them.

To work around this you can declare "dummy" vars of the classes you want to compile, or if using the flex compiler there are options to include the classes you are missing.

e.g. declare these anywhere in your project

private var p1:Product1Class;
private var p2:Product2Class;

Its a frustrating problem, if your classes extend MovieClip which is a dynamic class you might be able to access the properties etc by doing something like this:

var product:MovieClip = new productReference() as MovieClip;
p1["someCustomProperty"]; //Dot notation might work here as it is a dynamic class
于 2011-01-05T16:12:46.177 に答える
1

Chris is absolutely right, the ReferenceError is actually being thrown during the call to getDefinitionByName, meaning that the reflection method cannot find Product1Class or Product2Class in your application domain. You can always check if a definition is available by checking the application domain directly, like:

// inside your createProduct method, yields 'false'.
ApplicationDomain.currentDomain.hasDefinition( productClassName );

Are these library assets loaded in at runtime? If so, you can either make sure that the library swf is loaded into the current application domain by adding an appropriately configured LoaderContext to your Loader, or you can replace the call to getDefinitionByName with the loaded swf's application domain's getDefinition method.

于 2011-01-06T05:57:49.503 に答える