Fork me on GitHub

AS3使用自定义元数据标记,类似C#的类属性、成员属性

原创文章,未经允许,请勿转载

在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 
{ 
    /** 
     * ... 
     * @author yoyo 
     */ 
    [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; 

    /** 
     * ... 
     * @author yoyo 
     */ 
    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); 
            // describeType方法返回的信息类似下面的xml 
            /** 
               <type name="Test1" base="Object" isDynamic="false" isFinal="false" isStatic="false"> 
               <extendsClass type="Object"/> 
               <variable name="s" type="String"> 
               <metadata name="BindData"> 
               <arg key="param1" value="abc"/> 
               </metadata> 
               <metadata name="__go_to_definition_help"> 
               <arg key="pos" value="131"/> 
               </metadata> 
               </variable> 
               <metadata name="Inject"/> 
               <metadata name="__go_to_ctor_definition_help"> 
               <arg key="pos" value="173"/> 
               </metadata> 
               <metadata name="__go_to_definition_help"> 
               <arg key="pos" value="79"/> 
               </metadata> 
               </type> 

             */ 

            var t:Test1 = new Test1();   

            initMeta(t); 

            trace(t.s);//打印修改后的值 
        } 

        /** 
         * 开始对这个对象进行注入 
         * @param   obj 
         */ 
        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); 
            } 
        } 

        /** 
         * 获取含有自定义标签的类对象 
         * @param   xml 
         */ 
        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; 
                } 
            } 
        } 

        /** 
         * 获取含有自定义标签的成员变量 
         * @param   xml 
         */ 
        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; 
                } 
            } 
        } 

    } 
}

来源:悠游悠游,原文地址:https://yymmss.com/p/186.html