Listing class properties dynamically in AS3
Posted by: Keith H in Flash 9, Flex, XML, tags: describeType, ObjectUtil.getClassInfo, RegExp, XMLDynamically listing the properties of a class is pretty cool and useful. There are many things you could do by generating a list of existing properties. One example is you can make your class instances represent themselves dynamically in a custom format of your choosing. Like how "toString()" is use with the Array class or how Point is represented when toString() is called from it. Going further, listing current properties could be used to save the current values of the class as a "save point".
In the Flex framework, there is ObjectUtil.getClassInfo().properties, but I feel is more useful to just use the XML returned from the describeType method. I like using decribeType for both plain AS3 or when using the Flex framework because its accessible in both.
Since the return of describeType is XML I have more options with E4X filtering/Regular Expressions, than using getClassInfo(). With describeType I can get info on methods as well but to keep things simple I'm only talking about accessor properties in this post. Using the "listProperties" function, I am listing the properties between 3 different classes. This is a function I wrote to show how you can make your own way to use the XML of decribeType.
In the example SWF below, there are 3 classes under inspection. The Helicopter class is a custom class extending Sprite. By setting the parameters of listProperties you can list the properties of Helicopter, or all of the properties it has by being subclassed from Sprite. The other classes are a TextField and a Sprite class. Changing the options lists a different set of properties based on type of Class of properties listed and what class its properties are declared by.
The custom Helicopter class extending Sprite
package { import flash.display.Sprite; public class Helicopter extends Sprite { private var _roll:Number=0; private var _pitch:Number=0; private var _yaw:Number=0; function Helicopter():void { super(); } public function get roll():Number { return _roll; } public function set roll(v:Number):void { _roll=v; } public function get pitch():Number { return _pitch; } public function set pitch(v:Number):void { _pitch=v; } public function get yaw():Number { return _yaw; } public function set yaw(v:Number):void { _yaw=v; } } }
/*============================================================ obj -The instance to return properties of. accessType -Set to either "readwrite" or "readonly" to return only those kind of properties. excludeCommonWith -Excludes all properties 'obj' has in common with the Class you give here. matchesRE -If set listProperties will only return the property names that match the RegExp. declaredOnlyByObjClass -If false, will not exclude properties declared by other classes than the givin 'obj'. Returns and Array of all the properties of the instance. ============================================================*/ function listProperties(obj:Object, accessType:String="readwrite", excludeCommonWith:Class=null, matchesRE:RegExp=null, declaredOnlyByObjClass:Boolean=true):Array { var a:XMLList; var b:Array=[]; var c:*; var n:int; var doc:XML; var cname:String; matchesRE=matchesRE || new RegExp(".+"); accessType=accessType || "readwrite"; accessType=accessType.toLowerCase(); if (!RegExp(/readwrite|readonly/i).test(accessType)) { accessType == "readwrite"; } doc=flash.utils.describeType(obj); cname=doc.@name; if (declaredOnlyByObjClass) { a=doc.accessor.(@access == accessType && @declaredBy == cname && matchesRE["test"](@name)); } else { a=doc.accessor.(@access == accessType && matchesRE["test"](@name)); } if (excludeCommonWith != null) { c=new excludeCommonWith(); } n=0; while (n < a.length()) { if (c != null) { if (Object(c).hasOwnProperty(a[n].@name) == false) { b.push(a[n].@name); } } else { b.push(a[n].@name); } n++; } return b; }
Entries (RSS)
Hey Keith,
you might want to check out as3-reflect which is part of the as3commons library, it provides a simple API for the XML reflection data:
http://www.as3commons.org/as3-commons-reflect/index.html
cheers,
Roland