2009-04-27 13 views
2

J'essaie d'implémenter un système de plugin pour notre application, et étant donné que le fichier SWF est chargé dynamiquement, chargez des fichiers SWF supplémentaires.Créer des plugins dans Flex - charger des fichiers SWF imbriqués

Il va quelque chose comme ceci:

  1. Application principale charge Shell ...
  2. + --------- charges d'application ...
  3. ------ ----------- + Plugin (s)

Je n'ai pas de problème pour l'application # 1 pour charger l'application # 2

Cependant, essayez comme je pourrais, je ne peux pas l'application # 2 à charger et à stantiate # 3

J'ai essayé plusieurs permutations en utilisant le ModuleManager, mais c'est le plus proche. Lorsque la méthode onLoadComplete est invoquée, je peux voir que le fichier SWF est chargé, mais la fabrique renvoie toujours la valeur NULL.

Ce qui est intéressant, c'est que lorsque j'extrais ceci dans sa propre application, cela fonctionne très bien. Ce problème est dû au fait que je charge le plugin à partir d'un fichier SWF chargé dynamiquement. Je crois que cela est dû au ApplicationDomain, mais je ne peux pas faire la tête ou la queue de celui-ci. J'ai essayé de spécifier currentDomain, new ApplicationDomain(Application.currentDomain) et new ApplicationDomain() sans succès.

Aussi, il est important de noter que je ne peux pas faire référence à une référence à la classe Foo dans les deux applications, car de par leur nature, nous ne saurons pas à l'avance ce qu'ils vont contenir.

Googlin ', cela semble être un problème assez connu, mais je n'ai pas encore trouvé de solution (claire).

. 
. 
. 
assetModule = ModuleManager.getModule("Foo.swf");  
assetModule.addEventListener(ModuleEvent.READY, onLoadComplete); 
assetModule.addEventListener(ModuleEvent.ERROR, onLoadError); 
assetModule.load(); 
. 
. 
. 
private var _pluginInstance:Plugin; 

private function onLoadComplete(event:Event):void 
{ 
    trace("module loaded"); 

    _pluginInstance = assetModule.factory.create() as Plugin; 
    if(_pluginInstance) 
     _pluginInstance.startup(); 
    else 
     Alert.show("unable to instantiate module"); 
} 

private function onLoadError(event:Event):void 
{ 
     Alert.show("error"); 
} 

My Plugin looks like this: 

package 
{ 
    import mx.collections.ArrayCollection; 
    import mx.modules.ModuleBase; 

     public class Plugin extends ModuleBase 

     public function startup():void 
     { 

     } 
. 
. 
. 
} 

et

package 
{ 
    import Plugin; 
    import mx.modules.ModuleBase; 

    public class Foo extends Plugin 
    { 
     public function Foo() 
     { 
      trace("foo constructor invoked"); 
     } 

     override public function startup():void 
     { 
        trace("foo started"); 
     } 
. 
. 
. 
} 
+1

Je n'ai pas travaillé avec des domaines d'application dans un temps long, je ne peux pas donner une réponse complète à votre question, mais je peux vous dire que le problème se produit ici: assetModule.factory.create() en tant que plugin; La classe Plugin de votre module et la classe Plugin de votre application principale ne sont pas identiques en ce qui concerne la VM. Casting avec "as Plugin" renvoie null car Plugin! = Plugin. Comment contourner cela (autre que le lancer en tant qu'objet ou quelque chose), je ne me souviens pas, mais vous êtes sur la bonne voie d'enquêter sur la classe ApplicationDomain. – joshtynjala

Répondre

0

@ joshtynjala est exact. J'ai trouvé que j'essayais juste d'utiliser Object puis d'appeler des méthodes dessus (ne pas lancer).

var MyPlugin: Object = getPlugin(); MyPlugin.doPluginFunc();

Généralement, le cast entre les classes système/flex n'est pas un problème. Je ne sais pas si mettre Plugin comme une bibliothèque d'exécution aiderait?

0

Si vous voulez vraiment utiliser une interface commune entre votre plugin et votre application, la classe Plugin de votre application doit être la même que la classe Plugin de votre plugin. Pour ce faire, ils doivent être dans le même ApplicationDomain.

//In an external library 
public interface Plugin {} 

//In your application 
_pluginInstance = assetModule.factory.create() as Plugin; 
... 


//In your plugin 
public class MyPlugin implements Plugin 

Le problème est que, lorsque vous compilerez votre plugin swf, vous compilerez également Plugin. Ce n'est pas un problème, mais vous devez dire à votre demande que c'est le même que le sien:

var loader:Loader = new Loader(); 
loader.addEventListener(Event.COMPLETE, onLoadComplete); 
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));  

ApplicationDomain.currentDomain est la clé ici.Si vous faites référence à docs:

Domaine d'application du chargeur. Vous utiliser ce domaine d'application lors de l'utilisation ApplicationDomain.currentDomain. Lorsque la charge est terminée, parent et enfant peuvent utiliser directement les classes de l'autre. Si l'enfant tente de définir une classe portant le même nom qu'une classe déjà définie par le parent, la classe parent est utilisée et la classe enfant est ignorée.