Injecting a uint into a signal command

Conrad Winchester's Avatar

Conrad Winchester

21 Mar, 2010 03:08 PM

Hi

I am loving Robotlegs and signals - they seem to be a very natural fit. However I have run into an issue whilst trying to inject a uint - the mapping looks like this

        `signalCommandMap.mapSignalClass(LoadCollection, LoadCollectionCommand);`

the command looks like this

`package org.fwg.collectionviewer.controller {

import org.fwg.collectionviewer.comms.IGalleryService;
import org.robotlegs.mvcs.Command;

public class LoadCollectionCommand extends Command
{

    [Inject]
    public var galleryService:IGalleryService;

    [Inject]
    public var collectionId:uint;

    public override function execute():void
    {
        galleryService.requestCollection(collectionId);
    }


}

}`

But when I do something like

loadCollection.dispatch(227)

I get the following error

Error: Injector is missing a rule to handle injection into target [object LoadCollectionCommand]. Target dependency: uint

Any clues?

  1. 1 Posted by Stray on 21 Mar, 2010 03:41 PM

    Stray's Avatar

    Hi Conrad,

    What does the LoadCollection signal look like?

    I'm assuming it does

    super(uint) in the constructor?

  2. 2 Posted by marteinn on 21 Mar, 2010 04:37 PM

    marteinn's Avatar

    I encountered the same problem just the other day and soon realized that switching from int to Number solved the issue. Its not the perfect solution but it works.

    Cheers
    / M

  3. Support Staff 3 Posted by Till Schneidere... on 21 Mar, 2010 06:13 PM

    Till Schneidereit's Avatar

    Conrad and marteinn,

    I'm not entirely sure, but I think that's caused by a bug in
    SwiftSuspenders that misinterprets ints and uints as numbers when
    mapping values. This should be resolved in the current beta of
    SwiftSuspenders 1.5.
    If you want to try using that beta version (which is very stable and
    should have production quality IMO), you can do so by downloading it
    from the SwiftSuspenders downloads
    page
    and
    putting the contained SWC file into your project's libs folder.

  4. Support Staff 4 Posted by Joel Hooks on 21 Mar, 2010 06:14 PM

    Joel Hooks's Avatar

    Hey Till, there is an issue with Vectors too along the same lines...

  5. 5 Posted by Conrad Winchest... on 21 Mar, 2010 06:16 PM

    Conrad Winchester's Avatar

    Yep - the signal does have super(uint) in it, and switching to Number does inded make it work - will have to look at the source code of SwiftSuspenders as that is where the error occurs.

  6. Support Staff 6 Posted by Till Schneidere... on 21 Mar, 2010 06:55 PM

    Till Schneidereit's Avatar

    As I said, the SwiftSuspenders 1.5 shouldn't have that issue as of
    beta 4 (I think). Jon Toland made me aware of the issue and kindly
    provided a patch that resolved it, too.

    Vectors are another issue, unfortunately. While I could add an
    exception for them, too, that would make SwiftSuspenders incompatible
    with Flash Player 9. Currently, I think there are still too many
    projects that don't really require anything only Flash Player 10
    provides and should thus target 9.

    An option would be to add preprocessing rules to the source code and
    provide SWCs for FP 9 and 10. Patches for that are very welcome - I
    won't be able to implement that myself for at least the next couple of
    weeks.

  7. 7 Posted by Stray on 21 Mar, 2010 07:14 PM

    Stray's Avatar

    On the Vector issue, I'm working around it by using a wrapper class on the occasional Vector. I prefer not to inject the base classes but one of my signal command mappings does need it.

    I hadn't really sussed out why it wasn't working - just that it wasn't, and the first work around I tried happened to work so I stuck with it.

  8. 8 Posted by Conrad Winchest... on 21 Mar, 2010 07:17 PM

    Conrad Winchester's Avatar

    OK,

    I built Robot Legs againt the 1.5 beta of Swift suspenders - A lot of tests fail, but the resulting swf is usable (?) and when I run my application I get the same error - probably something fishy going on - am going with Number hack for the moment.

    Conrad

  9. 9 Posted by Daniel on 30 Apr, 2010 01:11 AM

    Daniel's Avatar

    The problem still exists in 1.5 beta. I'm trying to use a DisplayObject as the payload in my signal and I get the same error. If I change the type to String. Everything works fine and my command gets instantiated and executed.

  10. Support Staff 10 Posted by Till Schneidere... on 30 Apr, 2010 10:33 AM

    Till Schneidereit's Avatar

    That sounds like it's a different problem. Maybe you're using
    DisplayObject as the type to be injected into your signal when the
    actual mapped payload is a Sprite or MovieClip?

    Unfortunately, it's not possible to efficiently implement automated DI
    for injecting sub-types of the requested type (in this example,
    letting Sprite, Shape or MovieClip mappings satisfy a request for
    DisplayObject), so you have to match your mappings to your injection
    points exactly.

    If none of the above fits your problem, maybe you could attach a
    reduced test-case exposing your problem to the ticket?

  11. 11 Posted by Daniel on 30 Apr, 2010 04:55 PM

    Daniel 's Avatar

    I wasn't aware of the limitation with DI. Let me know if I should open a ticket for the following scenario

    I'm use the popup manager to display a popup from within a command and want to send the parent displayobject via signal to command. So where I dispatch the signal,

    // where I dispatch I have mySignal.dispatch( myComponent as DisplayObject);

    // signal command [Inject] public var parent:DisplayObject;

    As a workaround, I used the Application object to get the root display object so no longer needed to pass in the parent display object, but I thought this should still work.

  12. Support Staff 12 Posted by Till Schneidere... on 02 May, 2010 04:14 PM

    Till Schneidereit's Avatar

    To be honest, I'm not that well acquainted with the signals extension,
    so I'm not too sure what's going on behind the scenes between your
    "mySignal.dispatch" and the command creation.

    Still: If I understand correctly, the SignalCommandMap creates a
    temporary injector mapping for all payload items of the signal, so
    that these items can be injected into the then created command, right?

    If so, there's no need to open a ticket: It's simply not feasible to
    create temporary mappings for anything but the concrete type of the
    payload. In cases where you're creating the injector mappings
    yourself, you can easily map a super type to a sub type value (e.g.
    injector.mapValue(DisplayObject, new Sprite())), but in cases where
    the system creates the mappings for you, as is the case in the
    SignalCommandMap, it can't know which type you want to have mapped, so
    it has to use the concrete type. (See
    http://github.com/darscan/signals-extensions-CommandSignal/blob/master/src/org/robotlegs/base/SignalCommandMap.as#L93
    for how this works).

    The only thing you can do in this case (apart from working around the
    issue altogether as you did for now) is to change your injection:
    [Inject]
    public var parent:Sprite;

  13. 13 Posted by Conrad Winchest... on 05 Jun, 2010 04:28 PM

    Conrad Winchester's Avatar

    Woah! I fixed the uint bug and know what is causing it and it isn't very nice :-( This bug affected ints as well and is caused by what I can only consider to be a bug in the flash player.

    It turns out that if you have

    var a:uint=0;

    OR

    var a:int=0;

    then a.constructor is Number - this is absolutely wrong :-(

    SignalCommandMap then fails and need the following change

        protected function getConstructorForObject(object:Object):Class
        {
            var constructor:Class;
            if(object is Proxy || object is XML)
            {
                var name:String = getQualifiedClassName(object);
                constructor = Class(getDefinitionByName(name));
            }
            else if (object is uint)
            {
                constructor = uint;
            }
            else if (object is int)
            {
                constructor = int;
            }
            else
            {
                constructor = object.constructor;
            }
            return constructor;
        }
    

    Then all is well

  14. 14 Posted by Philipp on 05 Jun, 2010 06:21 PM

    Philipp's Avatar
  15. 15 Posted by Conrad Winchest... on 06 Jun, 2010 08:03 AM

    Conrad Winchester's Avatar

    STOP!!! I was wrong, this does not fix the problem. It turns out that the AVM2 treats Numbers, uints and ints in a very strange way and you can never be sure you have what you want. So I have another fix that does seem to work. You need to use the valueClasses array from the Signal rather than getConstructorForObject in order to map the injection. the code looks like this

    protected function routeSignalToCommand(signal:ISignal, valueObjects:Array, commandClass:Class, oneshot:Boolean):void
    {

            createCommandInstance(signal.valueClasses, valueObjects, commandClass).execute();
    
            if ( oneshot )
                unmapSignal( signal, commandClass );
        }
    
        protected function createCommandInstance(valueClasses:Array, valueObjects:Array, commandClass:Class):Object
        {
            var tempInjector:IInjector = injector.createChild();
            for (var i:uint=0;i<valueClasses.length;i++)
            {
                tempInjector.mapValue(valueClasses[i], valueObjects[i]);                
            }
            return tempInjector.instantiate(commandClass);
        }
    

    This seems to work as you would expect.

    I have offered this to Joel as a patch, along with some tests. He might include it in the official release of SignalCommandMap

  16. Support Staff 16 Posted by Joel Hooks on 06 Jun, 2010 08:06 AM

    Joel Hooks's Avatar

    Looks good to me :>

    As long as the tests pass I love seeing code getting nuked.

  17. 17 Posted by Conrad Winchest... on 07 Jun, 2010 05:32 AM

    Conrad Winchester's Avatar

    So, just to confirm, the current version of SignalCommandMap now supports injection of ints and uints into commands.

  18. Stray closed this discussion on 10 Feb, 2011 04:11 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac