Query the Loaded Classes in Flex / AS3

One of the things I love most about programming is running into walls and then finding creative ways to get over (or through) them. The most recent wall I ran into with Flex was that I wanted to be able to find classes at runtime that either implement a given interface or have specific metadata on them. Flash Player doesn’t provide an API to do this directly so I went searching for a workaround. Christophe Herreman tipped me off to a few great utilities for doing this:

A Flex application (using the Flex framework or AS3 only) can use getDefinitionNames to query any loaded SWF file (Application, Module, etc) for its class definitions. The getDefinitionNames utility just parses through the loaded bytecode and finds the class definitions. Then the as3-commons-reflect library can help determine which of those classes implement a given interface or have specific metadata on them. Here is an example:

(source code)

Here is how it works:

    var a:Array = getDefinitionNames(systemManager.loaderInfo);
 
    allClasses.dataProvider = a;
 
    ifooClasses.dataProvider = new ArrayCollection();
    metafooClasses.dataProvider = new ArrayCollection();
 
    for each (var cn:String in a)
    {
      var t:Type = Type.forName(cn);
      for each (var md:MetaData in t.metaData)
      {
        if (md.name == "MetaFoo")
        {
          metafooClasses.dataProvider.addItem(cn);
          break;
        }
      }
 
      if (ClassUtils.getImplementedInterfaceNames(t.clazz).indexOf("IFoo") >= 0)
      {
        ifooClasses.dataProvider.addItem(cn);
      }
    }

Pretty cool! There are a number of fun uses for this kind of thing… Modular IOC containers, client-side plugins, etc.

Getting over this wall was pretty easy thanks to Denis and Christophe. The Flex / AS3 community rocks!

This entry was posted in ActionScript, Flex. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • http://www.springactionscript.org Roland Zwaga

    Nice post James!
    One thing though, I think this would be a neater way of doing the interface check:

    ClassUtils.isImplementationOf(t.clazz, IFoo);

    cheers,

    Roland

  • http://www.springactionscript.org Roland Zwaga

    Hehe, ow, and while I’m at it, the Type class has a hasMetaData() method:

    t.hasMetaData(“MetaFoo”);

  • http://www.jamesward.com James Ward

    Awesome! Thanks Roland! That simplifies the code quite a bit.

    -James

  • http://www.leafedbox.com Ben Johnson

    I was actually trying to figure out a solution for this last night. Thanks for the timely post, James.

  • http://www.visible-form.com/blog Rich Rodecker

    Wow, I was just in need of this stuff this morning, thanks!

  • http://www.jamesward.com James Ward

    The new more cleaner code based on Roland’s suggestions is:

        var a:Array = getDefinitionNames(systemManager.loaderInfo);
     
        allClasses.dataProvider = a;
     
        ifooClasses.dataProvider = new ArrayCollection();
        metafooClasses.dataProvider = new ArrayCollection();
     
        for each (var cn:String in a)
        {
          var t:Type = Type.forName(cn);
     
          if (t.hasMetaData("MetaFoo"))
          {
            metafooClasses.dataProvider.addItem(cn);
          }
     
          if (ClassUtils.isImplementationOf(t.clazz, IFoo);
          {
            ifooClasses.dataProvider.addItem(cn);
          }
        }

    Much nicer! Thanks again Roland.

    -James

  • http://www.bolt3d.org Matt Bolt

    You might want to note that when using SWCs, this will not work unless it is fully included. Otherwise, the class has to be referenced prior to the “search” as flash uses an on demand system for library classes. Otherwise, hats off to you! Great little tool!

  • http://www.jamesward.com James Ward

    Hi Matt,

    Thanks for clarifying. Classes don’t get linked in unless they are explicitly referenced. In the full source you can see how I force that:

        if (0)
        {
          var someClasses:SomeClasses = new SomeClasses();
        }

    -James

  • Vivian

    James, I am from SF bayarea and its been a while since you came and delivered any presentation here in San Francisco or San Jose! How can we schedule couple of events with you here in the bay area. By the way our user group name in Silvafug and we meet in Adobe offices in SF and SJ, twice every month. You have been to our meetings before but that was long time back.

  • http://www.jamesward.com James Ward

    Hi Vivian,

    Please email me so we can figure out a time that might work. jaward at adobe dot com

    -James



  • View James Ward's profile on LinkedIn