Frage

Anstatt eine hartcodierte Switch-Anweisung zu verwenden, in der Sie den Zeichenfolgenamen einer Klasse übergeben und dann die entsprechende Klasse instanziiert, möchte ich den tatsächlichen Namen der Klasse an meine Werksmethode übergeben und eine Instanz dynamisch erstellen lassen dieser Klasse. Ich dachte, es wäre trivial und bin überrascht, dass es nicht funktioniert. Mir muss etwas ganz einfach fehlen:

Beispielcode:

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?");
    }
 }

Das einzige, was ein wenig seltsam sein mag (nicht sicher), ist, dass diese "Produkte" tatsächlich verknüpfte Bibliotheksartikel sind (dh: Ich habe einen Movieclip in der Bibliothek, der eine Verknüpfung mit Product1Class und eine andere zu Product2Class hat, die ProductBaseClass verlängern, was wiederum Movieclip erweitert.

Warum der ReferenzError?

War es hilfreich?

Lösung 3

getDefinitionByName () und applicationDomain.currentdomain.hasdefinition () erfordern Voll qualifizierte Klassennamen. Der Beispielcode im ursprünglichen Beitrag funktioniert, wenn Product1Class und Product2Class im Standardpaket enthalten sind. Wenn Sie jedoch die Produktklassen in ein anderes Paket verschieben, müssen Sie sicherstellen, dass Sie den Namen des voll qualifizierten Klassen an getDefinitionByName () liefern.

Wenn wir also unsere Produktklassen in com.example.Products einfügen, wird der Anruf:

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

Ich bin mir nicht sicher, was die beste Praxis mit dieser Art von dynamischer Fabrikklasse ist, aber was ich am Ende getan habe (da alle Produkte im selben Paket waren), war es, eine Konstante in meiner Fabrikklasse zu erstellen, die das Paket für meine definiert Produkte:

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

Auf diese Weise muss Ihr Client -Code das Produktpaket nicht kennen (noch definieren). Sie bereiten diese Konstante nur auf Ihren Produktklassennamen vor, wenn Sie GetDefinitionByName () verwenden.

Andere Tipps

Wenn Sie eine Laufzeit -ladenbibliothek haben, werden die Klasse nicht in das Haupt -SWF zusammengestellt, sodass Sie den Laufzeitreferenzfehler erhalten, wenn Sie versuchen, sie zu erstellen.

Um dies zu umgehen, können Sie "Dummy" -Vars der Klassen deklarieren, die Sie kompilieren möchten, oder wenn Sie den Flex -Compiler verwenden, gibt es Optionen, um die von Ihnen fehlenden Klassen einzuschließen.

ZB deklarieren Sie diese überall in Ihrem Projekt

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

Es ist ein frustrierendes Problem, wenn Ihre Klassen MOVIECLIP erweitern, einer dynamischen Klasse, die Sie möglicherweise auf die Eigenschaften zugreifen können usw., indem Sie so etwas tun:

var product:MovieClip = new productReference() as MovieClip;
p1["someCustomProperty"]; //Dot notation might work here as it is a dynamic class

Chris hat absolut Recht, der ReferenzError wird während des Anrufs tatsächlich geworfen getDefinitionByName, was bedeutet, dass die Reflexionsmethode nicht finden kann Product1Class oder Product2Class in Ihrer Anwendungsdomäne. Sie können jederzeit überprüfen, ob eine Definition verfügbar ist, indem Sie die Anwendungsdomäne direkt überprüfen, z. B.:

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

Werden diese Bibliotheksgüter zur Laufzeit eingeladen? In diesem Fall können Sie entweder sicherstellen, dass die Bibliothek SWF in die aktuelle Anwendungsdomäne geladen wird LoaderContext an Ihren Lader, oder Sie können den Anruf an ersetzen getDefinitionByName mit den Anwendungsdomänen des geladenen SWF getDefinition Methode.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top