Mar 18

Instantiating ActionScript 3.0 classes at runtime, and a Flex compiler trick

Tag: FlexDerek Wischusen @ 3:49 am

I’ve been playing around with dynamically instantiating classes in AS 3.0 a lot lately and I thought I would share a couple of tricks that I’ve come across.

You can instantiate a class at runtime using the getDefinitionByName(name:String):Object method in the flash.utils package. To use this method, you simply have to pass it the name of the class that you want to create.

Here are couple good posts that explain how to use this method:

Both of these posts point out that one of the limitations of this method is that the class that you want to create needs to be compiled into your application and that Flex only compiles in classes that are explicitly referenced in your application. This is obviously a major drawback, since one the main reasons that you would want to use dynamic instantion is to create classes that are not already referenced in you app.

So, I did a little searching and I found that there is a way to instantiate a class at runtime that is not explicitly referenced in your application.

Here’s how:

1. Put the classes that you want to instantiate at runtime in a Flex Library Project.

2. In the project for your application, add the .swc that is generated by the library project to the library path.

3. In the compiler arguments for your application add -include-libraries <path_to_swc>

The -include-libraries compiler argument tells the compiler that you want to load all of the classes in the library, even the ones that are not referenced anywhere.

Once you’ve done this, you will be able to load any of the classes in the library at runtime.

Now for the compiler trick:

If you go into the application that loads the library and create classes that have same name and namespace as the classes in your library project, the compiler will load the classes that are in your main application. This means that the library project only needs to contain empty classes that mirror the classes in your application that you want to instantiate at runtime.

For example, let’s say that you have a class called GetUser that you want to instantiate at runtime. If you follow the instructions from above you will have a Flex Library Project and Flex application that loads the SWC that is generated by the library.

Now, let’s say that you’ve put the AddUser class in the following package in your library project

com.mycomp.myproj.command.AddUser

If you put an AddUser class in the com.mycomp.myproj.command package in your Flex application project, when you instantiate the class at runtime the Flex will create the class that is in your Flex application project.

WARNING: The tricks that I described seem to make Flex very unhappy. If you want to test them out I suggest that you use new projects in a new workspace.

Please let me know if you have any questions about any of this.

3 Responses to “Instantiating ActionScript 3.0 classes at runtime, and a Flex compiler trick”

  1. Matjaz says:

    Hi,

    if you want to load and instantiate a class at run-time try this:
    1) compile a swf with a class you want to instantiate at run-time
    2) load the compiled .swf file into ApplicationDomain.currentDomain
    3) get the loaded class with ApplicationDomain.currentDomain.getDefinition(classPath) as Class

    Here is a class that does this:

    package klikfrikLib.utils.loaders
    {
    import flash.display.*;
    import flash.errors.*;
    import flash.events.*;
    import flash.net.*;
    import flash.system.*;
    import flash.display.Loader;
    import mx.controls.Alert;

    public class ClassLoader extends Loader
    {
    public static var CLASS_LOADED:String = “classLoaded”;
    public static var LOAD_ERROR:String = “loadError”;

    public function ClassLoader()
    {
    super()
    contentLoaderInfo.addEventListener(Event.COMPLETE,classLoaded)
    }

    private function classLoaded(ev:Event):void{
    var comEv:Event=new Event(Event.COMPLETE);
    dispatchEvent(comEv);

    }

    public function loadClass(filePath:String, classPath:String):void
    {
    if(ApplicationDomain.currentDomain.hasDefinition(classPath)){
    classLoaded(null)
    //mx.controls.Alert.show(”ClassLoader.loadClass = this class already loaded”);
    }else{
    var request:URLRequest = new URLRequest(filePath);
    var context:LoaderContext = new LoaderContext();
    context.applicationDomain = ApplicationDomain.currentDomain;
    try{
    load(request, context);
    }catch(er:Error){
    mx.controls.Alert.show(”ClassLoader can’t load= “+er.message);
    }
    }
    }

    public function getClass(classPath:String):Class
    {

    try
    {
    return ApplicationDomain.currentDomain.getDefinition(classPath) as Class;
    }
    catch(e:Error)
    {
    throw new IllegalOperationError(classPath + ” definition not found in ” + classPath);
    }
    return null;
    }

    }
    }

    And you use it like this:

    classLoader=new ClassLoader();
    classLoader.addEventListener(Event.COMPLETE, handleClassLoaded);
    classLoader.loadClass(filePathToSwf, classPath);
    private function handleClassLoaded(ev:Event){
    var clazz:Class=classLoader.getClass(classPath)
    var clazzObj=new clazz()
    }

    -Matjaz

  2. Richard Karpinski says:

    I have a wild idea of making the mouse do lots more. I want an entire zoom world to be accessible by just mousing. Rollover into a contained zone written smaller auto-zooms into it exactly to where the text is the natural size that the viewer prefers. Recursively.

    I’m thinking that if the contents of the zoom world are just text and images and maybe a video or two, then this is an almost trivial application of FlexibleRails. I expect to pay for an answer, and more for more detail about how and why.

    Having the content in a database would seem to permit arbitrary rearrangement on the fly without changing the application a whit and thus needing no new compile. Each region has a natural screen size and contains deeper regions without limit. Zooming in and out is automatic. Just mousing does all navigation needed to see the whole site. Then we can perhaps add command gestures, and still no buttons or keys until you are filling in some form. Still nearly trivial to implement in FlexibleRails.

    Is it possible that that is true? Or nearly true?
    Can I pay someone to answer questions like this?

    Richard Karpinski, World Class Nitpicker
    148 Sequoia Circle, Santa Rosa, CA 95401
    dick@cfcl.com Home +1 707-546-6760 Cell +1 707-228-9716

    ps Put (or leave) “nitpicker” in the subject line to get past my spam filters.

  3. Agilan palani says:

    Hi Matjaz,
    I tried the code which you gave. But it doesn’t help. It always gives IllegalOperationError. Iam struck up here. Will you provide the code which works for you?

    Thanks
    Agilan Palani

Leave a Reply