以下一個簡單的範例:
MyFirstRobotlegApp.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"
xmlns:ben="idv.ben.*">
<fx:Declarations>
<ben:MyContext id="myContext" contextView="{this}" />
</fx:Declarations>
<s:Button id="btn1" label="Test" x="200" y="200" />
</s:Application>
idv.ben.MyContext.as
package idv.ben
{
import flash.display.DisplayObjectContainer;
import idv.ben.controller.Btn1ClickCommand;
import idv.ben.controller.StartupCommand;
import idv.ben.event.MyEvent;
import idv.ben.mediator.MyMediator;
import org.robotlegs.base.ContextEvent;
import org.robotlegs.mvcs.Context;
public class MyContext extends Context
{
public function MyContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true)
{
super(contextView, autoStartup);
}
override public function startup():void{
mediatorMap.mapView(MyFirstRobotlegApp, MyMediator);
mediatorMap.createMediator(contextView);
commandMap.mapEvent(ContextEvent.STARTUP, StartupCommand, ContextEvent, true);
commandMap.mapEvent(MyEvent.UI_BTN1_CLICK, Btn1ClickCommand, MyEvent);
dispatchEvent(new ContextEvent(ContextEvent.STARTUP));
}
}
}
idv.ben.mediator.MyMediator.as
package idv.ben.mediator
{
import flash.events.MouseEvent;
import idv.ben.event.MyEvent;
import org.robotlegs.mvcs.Mediator;
public class MyMediator extends Mediator
{
[Inject]
public var viewComp:MyFirstRobotlegApp;
override public function onRegister():void{
viewComp.btn1.addEventListener(MouseEvent.CLICK, on_btn1_click);
}
private function on_btn1_click(e:MouseEvent):void{
dispatch(new MyEvent(MyEvent.UI_BTN1_CLICK));
}
}
}
idv.ben.controller.StartupCommand.as
package idv.ben.controller
{
import flash.utils.describeType;
import org.robotlegs.base.ContextEvent;
public class StartupCommand
{
[Inject]
public var event:ContextEvent;
public function execute():void{
trace(describeType(this)["@name"], "execute()", event);
}
}
}
idv.ben.controller.Btn1ClickCommand.as
package idv.ben.controller
{
import flash.utils.describeType;
import idv.ben.event.MyEvent;
public class Btn1ClickCommand
{
[Inject]
public var event:MyEvent;
public function execute():void{
trace(describeType(this)["@name"], "execute()", event);
}
}
}
idv.ben.event.MyEvent.as
package idv.ben.event
{
import flash.events.Event;
public class MyEvent extends Event
{
static public const UI_BTN1_CLICK:String = "uiBtn1Click";
public function MyEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
}
以上程式碼,簡單來說,進入主程式後會建立 Context,觸發 ContextEvent.STARTUP 事件執行 StartupCommand,另外會註冊 MyMediator 並於註冊時設定 btn1 的 MouseEvent.CLICK 處理函式,當發生時會送出 MyEvent.UI_BTN1_CLICK 給 Robotleg 的 shared eventDispatcher 讓有興趣的人處理,使得事先註冊好的 Btn1ClickCommand 被執行。
尚未混淆之前,執行畫面如下:
接下來,我使用 secureSWF 3.6 進行混淆,先使用 Standard 的 Protection Preset,若選擇 Most Aggressiv,受影響的範圍會更大,會影響到 Robotleg framework 中的其它程式碼。
選完 Standard 之後,預設我自定的 Custom Command 的 execute() 不會被勾選,這裡我先 故意 打勾:
開始進行混淆~
混淆後發現,secureSWF 會自動將我 Custom Command 的 execute() 取消勾選,我無法得知 secureSWF 的分析判斷依據。
這個版本的 swf 執行後當然也會是正常:
為了強迫測試 execute() 被混淆後的情況,我只好自己加 rule 將 idv.ben.controller.* 下的類別、method name 都進行更名:
這樣一來,測試結果 果然就出問題了:
Error: Command Class does not implement an execute() method - [class _-f]
這個範例只是要提醒注意,若 secureSWF 會幫我們避掉 execute() 最好 (可能在 Robotleg framework 中有使用到 execute,所以 secureSWF 避掉),但若是哪天 secureSWF 沒有避掉的話,就需要自己加 rule 來避掉這個問題了。
下面附上 Robotleg 的 CommandMap 片段程式碼,可幫助了解它執行 command (Object 類別) 的 execute() 的部分:
public function execute(commandClass:Class, payload:Object = null, payloadClass:Class = null, named:String = ''):void
{
verifyCommandClass(commandClass);
if (payload != null || payloadClass != null)
{
payloadClass ||= reflector.getClass(payload);
injector.mapValue(payloadClass, payload, named);
}
var command:Object = injector.instantiate(commandClass);
if (payload !== null || payloadClass != null)
injector.unmap(payloadClass, named);
command.execute();
}






0 意見:
張貼意見