2010-02-17 3 views
2

Utilisation de org.as3commons.reflect Je peux rechercher le nom de classe et instancier une classe lors de l'exécution. J'ai aussi du code (non fonctionnel) qui appelle une méthode. Cependant, je veux vraiment définir une valeur de propriété. Je ne suis pas sûr si les propriétés sont réalisées en tant que méthodes en interne dans Flex.Comment instancier dynamiquement une classe et définir une propriété à l'exécution dans Flex 3?

J'ai une classe de métadonnées qui stocke 3 informations: nom, valeur et type (toutes sont des chaînes). Je veux être en mesure de parcourir un tableau de métadonnées et définir les propriétés correspondantes sur la classe instanciée.

 

package com.acme.reporting.builders 
{ 
import com.acme.reporting.model.Metadata; 

import mx.core.UIComponent; 

import org.as3commons.reflect.ClassUtils; 
import org.as3commons.reflect.MethodInvoker; 

public class UIComponentBuilder implements IUIComponentBuilder 
{ 
    public function build(metadata:Array):UIComponent 
    { 
    var typeClass:Class = ClassUtils.forName(getTypeName(metadata)); 
    var result:* = ClassUtils.newInstance(typeClass); 

    for each (var m:Metadata in metadata) 
    { 
    if (m.name == "type") 
    continue; 

    // Attempting to invoke as method, 
       // would really like the property though 

    var methodInvoker:MethodInvoker = new MethodInvoker(); 

    methodInvoker.target = result; 
    methodInvoker.method = m.name; 
    methodInvoker.arguments = [m.value]; 

    var returnValue:* = methodInvoker.invoke(); // Fails! 
    } 

    return result; 
    } 

    private static function getTypeName(metadata:Array):String 
    { 
    if (metadata == null || metadata.length == 0) 
    throw new ArgumentError("metadata is null or empty"); 

    var typeName:String; 

    // Type is usually the first entry 
    if (metadata.length > 1 && metadata[0] != null && metadata[0].name == "type") 
    { 
    typeName = metadata[0].value; 
    } 
    else 
    { 
    var typeMetadata:Array = metadata.filter(
    function(element:*, index:int, arr:Array):Boolean 
    { 
     return element.name == "type"; 
    } 
    ); 

    if (typeMetadata == null || typeMetadata.length != 1) 
    throw new ArgumentError("type entry not found in metadata"); 

    typeName = typeMetadata[0].value; 
    } 

    if (typeName == null || typeName.length == 0) 
    throw new Error("typeName is null or blank"); 

    return typeName; 
    } 
} 
} 
 

est ici un code d'utilisation:

 

var metadata:Array = new Array(); 

metadata[0] = new Metadata("type", "mx.controls.Text", null); 
metadata[1] = new Metadata("text", "Hello World!", null); 
metadata[2] = new Metadata("x", "77", null); 
metadata[3] = new Metadata("y", "593", null); 

this.addChild(new UIComponentBuilder().build(metadata)); 
 

je me rends compte que je dois déclarer une variable fictive du type que je devais instancier ou utiliser la directive du compilateur -inculde. Un inconvénient malheureux de Flex.

De même, il existe actuellement un code pour rendre compte de la valeur typographique de son type spécifié.

Répondre

1

L'exécution dynamique dans AS3 est beaucoup plus simple que dans d'autres langues. Ce code:

var methodInvoker:MethodInvoker = new MethodInvoker(); 

methodInvoker.target = result; 
methodInvoker.method = m.name; 
methodInvoker.arguments = [m.value]; 

var returnValue:* = methodInvoker.invoke(); // Fails! 

peut être simplifié à ceci:

var returnValue:* = result[method](m.value); 

EDIT:

Depuis sa propriété, il serait fait comme ceci:

result[method] = m.value; 

et il n'y a pas de valeur de retour (bien, vous pouvez appeler le getter à nouveau, mais il devrait Il suffit de retourner m.value à moins que le setter/getter ne fasse quelque chose de funky.

+0

C'est génial pour réduire le code et la dépendance de MethodInvoker. Cependant, il échoue toujours dans mon cas puisque je veux vraiment définir une valeur de propriété. Par exemple, en utilisant l'exemple de métadonnée que j'ai spécifié ci-dessus, il échoue lorsqu'il obtient ce qui équivaut à résultat ["text"] ("Hello World!"): TypeError: Erreur # 1006: value n'est pas une fonction. Je suis sûr que c'est parce qu'il n'y a pas de méthode équivalente à la propriété "text". Une idée de comment l'obtenir pour travailler avec des propriétés? Je ne pense pas qu'il existe une méthode "setText" correspondante comme dans certaines langues. Je pourrais toutefois avoir tord. –

+0

@Edward Stembler, avez-vous essayé 'result [méthode] = m.value;'? Si c'est une propriété, définissez-la comme une propriété. –

+0

Eh bien, j'ai supprimé le code MethodInvoker et l'ai remplacé par var returnValue: * = result [m.name] (m.value); qui est le même que résultat ["text"] ("Hello World!") ;. Est-ce que méthode est un objet, ou puis-je utiliser une chaîne pour référencer une méthode (ou une propriété)? –

Questions connexes