explorers’ club


getDefinitionByName trick
Thursday, February 21, 2008, 11:20 pm
Filed under: actionScript, components, development, flash, flex

I am in the process of working on a ClassUtil class that will have static methods for creating class instances from generic objects and xml objects. One thing that I use in order to create nested content within the outer-most object to be created is getDefinitionByName. If you are not familiar with this method check it out. It basically returns a Class object by provide the name of the class in a string format. You want a Class object of String, then you pass “String”. You want the Class object for com.somesite.model.vo.SomeVo, the you pass “com.somesite.model.vo.SomeVo” as the parameter and whallah! You just have to remember to use the fully qualified class path in the string parameter.

This technique combined with using describeType and others yields some pretty powerful results. More on that later tho. So the issue with using getDefinitionByName is that unless you have instantiated an instance of the class in question, your swf will contain the embedded class definition. Then you run into the run-time-error saying that the variable of that name cannot be found (or something like that).

The most common way to resolve this is to put a useless instance of the class somewhere in your application. Such as var foo:Foopher = null. Then the class definition of Foopher is embedded in the compiled swf. Someone please correct me if I am wrong in explaining this. The problem with this solution is it seems rather hacky. It just doesn’t settle well with me. So I sought a different path.

The more uncommon way to resolve this is to define your class with a static var like so:

package vo
{
import flash.net.registerClassAlias;
[RemoteClass(alias="vo.NestedObject")]
public class NestedObject {
static private var _isRegistered:Boolean = false;
public var id:uint;
public var name:String; public function NestedObject ()
{
if (!_isRegistered)
{
registerClassAlias("vo.NestedObject", NestedObject);
_isRegistered = true;
}
}
}
}

Now it may be that registerClassAlias is a bit expensive but seeing as it is done once and only once per class type, this shouldn’t pose a problem. The other benefit is that you don’t clutter unrelated classes or views with having to make dummy instances to get it to register. Lastly, you can pick and choose which classes to use this method on so as to limit the price of making the call.


18 Comments so far
Leave a comment

[...] February 22, 2008 jwopitz – flex/flash exploration – getDefinitionByName trick http://jwopitz.wordpress.com/2008/02/21/getdefinitionbyname-trick/ [...]

Pingback by Twitter Response from @axna « TweetTrack

This is actually how kuler.adobe.com works, using XML you can recreate the entire class object with nested children and even items in nested array that resolve to proper class.

Comment by Ketan

You don’t need to create an instance of a class to include it in the SWF, just reference the class by name (not through a string. Just having
ClassName;
is really all you need.

What you described, though, reminded me of something I made a while back:
http://www.senocular.com/?id=2.9

Comment by orboy

@orboy (or senocular, is that you? if so I am honored by your presence here)

Do you mean to say that all you have to do is include a ref to the class in the compiler options? I think I have read that you can do that, but I was opting for a more elegant solution in order to not have to include the class in any unnecessary places at compile time.

I would love to understand the process in which by using registerClassAlias how it actually includes the class in the compiled swf. Or how any non-instantiated class makes its way into a compiled swf to be dynamically created at run-time.

Comment by jwopitz

Thanks for the tip. What do you do if you have classes that extend this class? Seems like you may get into trouble there. Is just overwriting the constructor enough?

Comment by poorman

Well considering these are Value Objects, you usually don’t extend them. That is not to say I never do that, as I have, but generally since VOs are treated as mere data objects with specified props, I usually don’t.

But to answer the question, yes. The _isRegistered is a static prop so it would not be accessible to subclasses. You’d have to declare the constructor for the subclasses in order to register the proper value.

Comment by jwopitz

I can’t seem to get this to work without first instantiating an object. I tried it and I still had to create an instance of my class before getting rid of the error you describe in your post. It looks like I can do it 1 of 2 things:

1. put the following somewhere in my code.

var vo:VO;

2. or call the following before I try to create the object.

flash.net.registerClassAlias(”com.company.vo.VO”,VO);

Maybe I missed something in your example.

Comment by poorman

send me an email with a zip of your source and will try it locally on my test app. jwopitz (at) gmail

Comment by jwopitz

Thanks so much for posting this, it just saved my day!

Comment by SoxFan33

[...] all … check out this link for the answer to all your woes: Explorer’s Club He figured out a way to instantiate a class dynamically w/out the need for creating dummy vars, [...]

Pingback by [AS3] Force Class Import - Ultrashock Forums

So … what’s the usage then? I too am running into the same problem as poorman – having to still include the dummy vars.

Comment by Brandon Ward

Apparently, this code only work if you compile your swf with Flex, due to the [ ] syntax ([RemoteClass(alias="vo.NestedObject")])…

If you compile the swf with the flash IDE, the [ ] call should’nt be considered.

I had the same problem when I was trying to include fonts to the swf, without creating them in the library, but using the [] syntax, as described in the Colin Mook’s AS3 Book.

Could anyone confirm or cancel this assumption?

For those who can’t make the code working, are you devlopping with the Flash IDE?

For those who can get the code working, are you devlopping with the flex builder/sdk?

So far, the solution should be the found of a way to replace the [] call with an Flash IDE’s compiling option (if it exists!)…

Does anybody know something about that?

Comment by bone

The project I’m building is not in Flex so
I would really like to know if there is a way to accomplish this with just Flash (NOT flex).

I use class names passed from an XML doc and use getDefinitionByName to use the strings as classes.

So far I’ve created an (unused) array of all of the potential classes used which works but is really annoying ..

If there is a way to use the registerClass trick with Flash can someone please let us know?

Comment by Ptest

Have you tried it in flash? The metadata tags, registerClass and getDefinitionByName are all basic as3, irrespective of your use of Flex. I have not tried it myself in Flash but I would assume it works in Flash as it does in Flex.

Comment by jwopitz

Can someone give me a quick example of a no-frills way to call it? Using the initial NestedObject – quick and dirty on the timeline I’ve tried..

import vo.*;
import flash.utils.getDefinitionByName;
//var uselessArray:Array =[NestedObject];

var Klass:Class = getDefinitionByName(”vo.NestedObject”) as
Class;

// trace(getIt);
new Klass();

the only way it works is if I uncoment the
uselessArray part

Am I going about calling this class correctly?
thanks -

Comment by Ptest

hi,

i tried this in flash and it didn’t work.
i think it is the same problem like embedding somezhing with the [Embed()]

Comment by jivita

Hello,

As you describe above, I’ve tried using registerClassAlias to assign a static variable in the class definition AS3 (not Flex), and I still get the error:

ReferenceError: Error #1065: Variable MyClass is not defined.

Having applied your method above, I was trying to do something like this:

var dynClass:Class = Class(getDefinitionByName(”fully.qualified.MyClass”));
var dynObj = new dynClass();
addChild(dynObj);

Could you show a usage example? Thanks

Comment by sideDoor

I don’t quite understand how this works. You’re still pretty much explicitly defining the class you want to import. How is this any less work than doing the

Box;

trick ?

Comment by lqdice




Leave a comment
Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>