views:

605

answers:

3

Hi

I'm newish to flex an have recently hit a snag casting.

this is the code I'm running.

/**
* return background definition depending on time
*/ 
private function findBackgroundItem( relativeTime : Number ) : CSBackgroundItem
{
    if( this.backgroundItems == null ) return null;
    var result :CSBackgroundItem = null;
    var relative:Date = new Date(relativeTime);
    for( var i : Number = 0; i < this.backgroundItems.length; i++ )
    {
     // backgroundItems is an Ilist of CSBackgroundItem.
     var colourItem : CSBackgroundItem = CSBackgroundItem( this.backgroundItems.getItemAt( i ) );

     // other stuff here
    }   
    return result;
}

The problem occurs when the IList.getItemsAt() result is cast to the CSBackgroundItem variable colourItem. The following error is thrown

TypeError: Error #1034: Type Coercion failed: cannot convert com.mystuff::CSBackgroundItem@650e8dd1 to com.mystuff.CSBackgroundItem.

If I use the 'as' keyword I get cast results in the colourItem being null. Using the debugger shows that the list is not empty and is indeed populated with CSBackgroundItem objects.

Now this is the wacky bit.. this code works, the first time the module it's in loads.. subsequent loads (after unloading it) throw the exception.

Can anyone shed any light on why this might happen?

+1  A: 

I think I may have found the answer..

My guess is the module is loading in a different ApplicationDomain.. which would mean you can't cast from the same type in the current domain..

As I understand this is vaguely similart to different Java ClassLoaders loading the same class.

I'll post again once I've confirmed it

Scrimmers
+1  A: 

Yup.. that works..

here is the fix i used in MXML style..

<mx:ModuleLoader id="loader" x="10" y="10" width="100%" height="100%" applicationDomain="{ApplicationDomain.currentDomain}"/>

the equivilant actionscript would be

loader.applicationDomain = ApplicationDomain.currentDomain;
Scrimmers
+1  A: 

FYI, a type loaded into a child ApplicationDomain can be cast to a type (that it extends/implements) in the parent ApplicationDomain.

Eg.

loader.applicationDomain = ApplicationDomain.currentDomain; // parent domain
loader.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); // child domain
loader.applicationDomain = new ApplicationDomain(); // new domain
Richard Szalay
ah cool, in this case there was no inheritance of extension, but it's good to know
Scrimmers
The same concept applies to the types themselves. A child application domain will look up a type in it's parent before declaring it itself. In your case, you want CSBackgroundItem to be declared in the parent appdomain and only _referenced_ in the child.
Richard Szalay
I see what you mean.. there isn't really a 'need' for us to declare the CSBackgroundItem in the parent domain other than for this purpose.. but it will be useful for some domain objects
Scrimmers