在AS3 使用元数据标签最多的应该是swf标签了,如:
[SWF(backgroundColor = 0x000000, frameRate = 24, width = 1000, height = 600)]
那么能不能自定义我们自己的标签,然后在运行时,获取那些含有自定义标签的类或者类成员,然后达到注入的目的呢?答案是肯定的,在robotleg等一些开源框架中也用到了注入。
要是有元数据标签需要在编译器的扩展参数中指定-keep-as3-metadatac参数:
-keep-as3-metadata+=Inject,BindData
后面的Inject、BindData就是下面的例子要用的两个标签
需要注意的是这个编译参数只需要在一个运行库中指定即可,比如我们使用swc,那么编译这个swc指定了-keep-as3-metadatac参数,那么在使用swc的库的项目是不需要再指定的。在-keep-as3-metadatac参数使用“+=”是为了避免把别的参数定义覆盖掉。
比如Test1.as类使用元标签:
package
{
[Inject]
public class Test1
{
[BindData(param1="abc")]
public var s:String = 'ssss';
public function Test1()
{
}
}
};
接下来我们做注入操作,在不需要直接引用s成员的情况下,根据BindDta标签,修改这个成员变量的值:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.describeType;
import flash.xml.XMLNode;
public class Main extends Sprite
{
public function Main():void
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var t:Test1 = new Test1();
initMeta(t);
trace(t.s);
}
private function initMeta(obj:*):void
{
var xml:XML = describeType(obj);
var typeName:String = xml.@name;
initClassMeta(obj,typeName,xml);
for (var i:int = 0, len:int = xml.variable.length(); i < len;i++)
{
var variables:XML = xml.variable[i];
initVariableMeta(obj,typeName,variables);
}
}
private function initClassMeta(obj:*,typeName:String,xml:XML):void
{
for (var i:int = 0, len:int = xml.metadata.length(); i < len;i++)
{
var mata:XML = xml.metadata[i];
var metaName:String = mata.@name;
switch (metaName)
{
case 'Inject':
trace(typeName + ',Inject:' + metaName);
break;
}
}
}
private function initVariableMeta(obj:*,typeName:String,xml:XML):void
{
var name:String = xml.@name;
var type:String = xml.@type;
for (var i:int = 0, len:int = xml.metadata.length(); i < len;i++)
{
var mata:XML = xml.metadata[i];
var metaName:String = mata.@name;
switch (metaName)
{
case 'BindData':
trace(typeName + ',BindData:' + metaName + '(' + mata.arg[0].@value + ')');
obj[name] = 'inject';
break;
}
}
}
}
}