AS3 依赖注入


一、 AS3 注入基本知识

对于一个写Java的来说注入这个概念再熟悉不过了。Java Spring框架IOC机制被一个蛋疼的东西简单粗暴的借鉴到了actionscript中,这就是Robotlegs。所以就有了形如下面的应用:

//someplace in your application where mapping/configuration occurs
var myClassInstance:MyClass = new MyClass();
injector.mapValue(MyClass, myClassInstance);
//in the class to receive injections
[Inject]
public var myClassInstance:MyClass

当某个Class需要使用某个类实例的时候直接在声明的变量上面添加[Inject]元标签即可被框架自动赋值,这个方式大大的减少了开发工作量,作为一个深受As3蹂躏的客户端程序这时想到的是通过这一方式结束煎熬的素材引用问题。

当使用AS3开发网页游戏的时候,我们常常会用到很多Swf,这时SWF中的类属性(元件)引用就是一件麻烦的事儿。比如 A.swf 存在 链接名为A的显示对象,一般我们使用的时候常常会做如下操作

domain=new ApplicationDomain();  
domain = evt.currentTarget.applicationDomain;
var cls:Class=domain.getDefinition(name) as Class;
var a:A=new cls();
a.displayobj;

我们做了很多操作仅仅是为了拿到dispalyobj对象,通过Robotlegs的来的灵感,通过一个小技巧来减少我们的工作量。

具体就是使用describeType,关于上面这个方法不再赘述,点击链接 http://help.adobe.com/zh_CN/FlashPlatform/reference/actionscript/3/flash/utils/package.html

另外一个知识点 元数据,这个东西简单点说就是Flash内部对于AS3类描述的一种数据结构,具体的查看天地会关于元数据的描述http://wiki.9ria.com/index.php/%E5%9C%A8Flash%E4%B8%AD%E5%B5%8C%E5%85%A5%E5%85%83%E6%95%B0%E6%8D%AE%E6%A0%87%E7%AD%BE

二、 注入实现

现在开始是我们这道菜的重点,怎么实现自定义类与SWF中的现实对象关联。先上代码瞧瞧


package com.hans.core.utils
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.utils.Dictionary;
import flash.utils.describeType;

import avmplus.getQualifiedClassName;

/**
*ReflectUtil.as:
*<p>反射工具</p>
*@author:Hans
*@date:2012-4-15
*/
public class ReflectUtil
{

/**
*描述XML
*/
private var descriptXML:XML;
/**
*cache容器
*/
private var reflectCache:Dictionary;
/**
* ReflectUtil实例
*/
private static var _instance:ReflectUtil;

/**
* 构造反射实例
*
*/
public function ReflectUtil()
{
reflectCache = new Dictionary();
}
/**
* 映射素材
*
*/
public static function map2Res(reflectInstance:DisplayObject,resouce:DisplayObjectContainer):void
{
if(!_instance)
{
_instance = new ReflectUtil();
}
_instance.reflect(reflectInstance,resouce);
}
/**
* 将实际素材映射到目标Sprite上
* @param desc
* @param orgiRes
*
*/
private function reflect(target:Object,orgiRes:DisplayObjectContainer):void
{
this.descriptXML = describeTypeCache(target);
var list : XMLList = descriptXML.*;
var item : XML;
//缓存容器
var propMap:Dictionary = new Dictionary();
for each (item in list) {
var itemName : String = item.name().toString();
switch(itemName) {
case "variable":
propMap[item.@name.toString()] = item.@type.toString();
break;
case "accessor":
var access : String = item.@access;
if((access == "readwrite") || (access == "writeonly")) {
propMap[item.@name.toString()] = item.@type.toString();
}
break;
}
}
for(var prop:String in propMap)
{
var obj:Object = this.map(prop,orgiRes);
target[prop] = obj!=null ? obj : target[prop];
}
}
/**
* 映射素材元件
* @param property
* @param resouce
*
*/
private function map(property:String,resouce:DisplayObjectContainer):DisplayObject
{
var res:DisplayObject = resouce.getChildByName(property);
return res;
}
/**
* 获取xml描述
* @param desc
* @return
*
*/
private function describeTypeCache(desc:Object):XML
{
var name:String = getQualifiedClassName(desc);

if(!this.reflectCache[name])
{
this.reflectCache[name] = describeType(desc);
}
return this.reflectCache[name];
}

}
}