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.
21 Comments so far
Leave a comment
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

[...] 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 Friday, February 22, 2008 @ 12:06 amThis 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 Friday, February 22, 2008 @ 12:27 amYou 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:
Comment by orboy Friday, February 22, 2008 @ 1:14 amhttp://www.senocular.com/?id=2.9
@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 Friday, February 22, 2008 @ 4:40 pmThanks 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 Tuesday, March 4, 2008 @ 10:20 pmWell 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 Tuesday, March 4, 2008 @ 10:31 pmI 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 Tuesday, March 4, 2008 @ 11:24 pmsend me an email with a zip of your source and will try it locally on my test app. jwopitz (at) gmail
Comment by jwopitz Wednesday, March 5, 2008 @ 12:00 amThanks so much for posting this, it just saved my day!
Comment by SoxFan33 Friday, August 15, 2008 @ 3:53 pm[...] 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 Thursday, October 30, 2008 @ 7:48 pmSo … 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 Friday, October 31, 2008 @ 4:14 pmApparently, 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 Thursday, January 1, 2009 @ 10:51 amThe 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 Thursday, February 19, 2009 @ 7:51 pmHave 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 Thursday, February 19, 2009 @ 9:19 pmCan 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?
Comment by Ptest Thursday, February 19, 2009 @ 11:05 pmthanks -
hi,
i tried this in flash and it didn’t work.
Comment by jivita Monday, March 2, 2009 @ 12:31 ami think it is the same problem like embedding somezhing with the [Embed()]
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 Saturday, May 16, 2009 @ 9:20 pmI 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 Sunday, June 21, 2009 @ 5:41 pmGuys I figured out the perfect solution for my specific problem but I have a feeling you can tweak your code to behave in a similar way.
Comment by heyitsleo Sunday, August 2, 2009 @ 7:17 amvar classNames:Array = [ClassA, ClassB, ClassC];
var classInstances:Object = {};
for each (className:Class in classNames) {
classInstances.push(new className());
}
Hope that helps
If I understand this correctly, we no longer have to import the to be created class in the creating class, only in the to be created class do we register it as an alias.
So if we have A that we need to instantiate with getDefinitionByName(‘A’) and we do not want to import A, then in the definition of A we registerClassAlias(‘A’, A). Thereby we can use getDefinitionByName(‘A’) anywhere without first importing it.
As far as I can tell, by using registerAlias, we are including the class in the running SWF, which only needs to happen once to be able to use getDefinitionByName.
Hmm but this does bring up an interesting cat and mouse problem. If we need to first instantiate A to call registerAlias, then it would have already been imported, in which case we needn’t have registered it, because the class would need to be imported, loaded into the SWF, and instantiated somewhere for registerAlias to be called.
Comment by ben Tuesday, August 4, 2009 @ 4:00 pmFound this little trick that utilizes a metadata tag that compiles in classes for use with getDefinitionByName
http://www.rozengain.com/blog/2009/08/21/getdefinitionbyname-referenceerror-and-the-frame-metadata-tag/
Comment by jwopitz Friday, August 21, 2009 @ 6:07 pm