Monday, July 23, 2007

Using the introspection API

If you want to list all the public properties and methods of a nondynamic (or sealed) class or class instance, use the describeType() method and parse the results using the E4X API. The describeType() method is in the flash.utils package. The method's only parameter is the target object that you want to introspect. You can pass it any ActionScript value, including all available ActionScript types such as object instances, primitive types such as uint, and class objects. The return value of the describeType() method is an E4X XML object that contains an XML description of the object's type.

The describeType() method returns only public members. The method does not return private members of the caller's superclass or any other class where the caller is not an instance. If you call describeType(this), the method returns information only about nonstatic members of the class. If you call describeType(getDefinitionByName("MyClass")), the method returns information only about the target's static members.

The following example introspects the Button control and prints the details to TextArea controls:

<?xml version="1.0"?>

<!--
usingas/IntrospectionAPI.mxml -->
<
mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="getDetails()">

<
mx:Script><![CDATA[
import
flash.utils.*;

public function
getDetails():void {
// Get the Button control's E4X XML object description.
var classInfo:XML = describeType(button1);

// Dump the entire E4X XML object into ta2.
ta2.text = classInfo.toString();

// List the class name.

ta1.text = "Class " + classInfo.@name.toString() + "\n";

// List the object's variables, their values, and their types.
for each (var v:XML in classInfo..variable) {

ta1.text += "Variable " + v.@name + "=" + button1[v.@name] +
" ("
+ v.@type + ")\n";
}


// List accessors as properties.
for each (var a:XML in classInfo..accessor) {

// Do not get the property value if it is write only.
if (a.@access == 'writeonly') {
ta1.text += "Property " + a.@name + " (" + a.@type +")\n";
}


else
{
ta1.text += "Property " + a.@name + "=" +
button1[a.@name] + " (" + a.@type +")\n";
}
}


// List the object's methods.

for each (var m:XML in classInfo..method) {

ta1.text += "Method " + m.@name + "():" + m.@returnType + "\n";
}
}
]]></
mx:Script>

<
mx:Button label="Submit" id="button1"/>
<
mx:TextArea id="ta1" width="400" height="200"/>

<
mx:TextArea id="ta2" width="400" height="200"/>
</
mx:Application>


The output displays accessors, variables, and methods of the Button control, and appears similar to the following:
Class mx.controls::Button
...
Variable id=button1 (String)
Variable __width=66 (Number)
Variable layoutWidth=66 (Number)
Variable __height=22 (Number)
Variable layoutHeight=22 (Number)
...
Property label=Submit (String)
Property enabled=true (Boolean)
Property numChildren=2 (uint)
Property enabled=true (Boolean)
Property visible=true (Boolean)
Property toolTip=null (String)
...
Method dispatchEvent():Boolean
Method hasEventListener():Boolean
Method layoutContents():void
Method getInheritingStyle():Object
Method getNonInheritingStyle():Object

Another useful method is the ObjectUtil's getClassInfo() method. This method returns an Object with the name and properties of the target object. The following example uses the getClassInfo() and toString() methods to show the properties of the Button control:


<?xml version="1.0"?>

<!--
usingas/IntrospectionObjectUtil.mxml -->
<
mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<
mx:Script><![CDATA[
import
mx.controls.Alert;

import
mx.utils.ObjectUtil;
private function
showProps(b:Button):void {

var
o:Object = ObjectUtil.getClassInfo(b);
ta1.text = ObjectUtil.toString(o);
}
]]></
mx:Script>

<
mx:Button id="b1" label="Show Properties" click="showProps(b1)"/>

<
mx:TextArea id="ta1" width="300" height="500"/>
</
mx:Application>

No comments: