最近開始使用 RobotLegs,覺得還蠻好用的,可以少寫很多程式碼
雖然有一些效能上的問題,但可以透過自己管理創建/銷毀時機方式避開

當想要把它用在 Flex Module 開發時,又遇到了一些問題
找不到任何良好的 RobotLegs Modular 開發範例
雖然有人寫了 Modular Utilities,且有提供範例 ModularDoodads
但是坦白說,寫的很糟糕
Module 與主程式綁在一起,無法拆成獨立外部檔案

又有人基於 Modular Utilities 寫了另一個範例 DynModules
終於將 Module 拆成外部檔案了
不過仔細一看,原來它 Hard Code 硬將 Module 載入到 ApplicationDomain.currentDomain
表示 Module 永遠無法卸載,又是另一個骯髒的範例
於是只好自己想辦法解決這問題

我的初步需求很簡單,Module 並不需要與主程式共用 Context or Injector
Module 有自己獨立的 Context,只是與主程式共用 RobotLegs Lib. 而已
僅僅只是這樣都遇到了問題
以下便是簡化的測試程式:

Main.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  xmlns:s="library://ns.adobe.com/flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx">
 <fx:Script>
  <![CDATA[
   import org.robotlegs.mvcs.*;
 
   // include RobotLegs framework.
   Actor;
   Command;
   Context;
   Mediator;
  ]]>
 </fx:Script>
 <s:ModuleLoader url="modules/RLModule.swf" />
</s:Application>

modules/RLModule.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
  xmlns:s="library://ns.adobe.com/flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:modules="modules.*">
 <fx:Declarations>
  <modules:RLModuleContext contextView="{this}" />
 </fx:Declarations>
</s:Module>

modules/RLModuleContext.as

package modules {
 import flash.system.ApplicationDomain;
 
 import org.robotlegs.mvcs.Context;
 
 public class RLModuleContext extends Context {
 
  override public function startup():void{
   mediatorMap.mapView(RLModule, RLModuleMediator);
  }
 }
}

modules/RLModuleMediator.as

package modules {
 import org.robotlegs.mvcs.Mediator;
 
 public class RLModuleMediator extends Mediator {
 
  [Inject]
  public var view:RLModule;
 }
}

不管有沒有對 RLModule 最佳化,執行就會得到錯誤訊息

ReferenceError: Error #1065: 變數 RLModule 未定義。
 at flash.system::ApplicationDomain/getDefinition()
 at org.swiftsuspenders.injectionpoints::PropertyInjectionPoint/applyInjection()
 at org.swiftsuspenders::Injector/injectInto()
 at org.swiftsuspenders::Injector/instantiate()
 at org.robotlegs.base::MediatorMap/createMediatorUsing()
 at org.robotlegs.base::MediatorMap/mapView()
 at modules::RLModuleContext/startup()
 at org.robotlegs.mvcs::Context/onAddedToStage()
 at flash.display::DisplayObjectContainer/addChildAt()
 ...

花了一些時間在 RobotLegs 原始碼中找原因
才發現 Context 會替 mediatorMap, commandMap, viewMap 建立 childInjector
而 childInjector 又需要用到 contextView 的 ApplicationDomain
可是一開始 Module 還沒加到舞台上時,loaderInfo 是 null
備份方案變成改取 ApplicationDomain.currentDomain
也就是 Context 類別定義的那一個
當然裡面根本不會有 Module 的類別
結果就是一堆 Error

解決方式就是在 RLModuleContext 自行覆寫一次 getApplicationDomainFromContextView
內容直接從 super 抄一遍就好了

  override protected function getApplicationDomainFromContextView():ApplicationDomain{
   if (contextView && contextView.loaderInfo)
    return contextView.loaderInfo.applicationDomain;
   return ApplicationDomain.currentDomain;
  }

原始檔案下載