Mapping and Injection with base-classes/implementations regarding ViewComponents and Mediators

karfau's Avatar

karfau

21 Oct, 2009 07:49 PM

Since this site also exists, i wan't to try it for my first problem with RL:
Ich have the following Classes I talk about here:

  • MultiTextViewerBase.as
    public class MultiTextViewerBase extends SkinnableContainer...
    has all component-logic to handle multiple textElements.
  • StartPage.mxml
    <viewer:MultiTextViewerBase ...
    wich defines a text-layout and the mapping for textElements.
  • MultiTextViewerMediator.as
    public class MultiTextViewerMediator extends Mediator implements IMediator
    which knows everything that is needed to connect any implementation of MultiTextViewerBase to the app.

My first attempt to use StartPage (beside puting it on the displaylist) was to write the following inside context.startup():

mediatorMap.mapView(MultiTextViewerBase,MultiTextViewerMediator);

and this inside of MultiTextViewerMediator:

[Inject]
public var view:MultiTextViewerBase;

but with this there was no Mediator registered for StartPage (what i can see in the log and from the "non-behaviour" of the component).

so thinking maybe it needs the concrete class of the component to make mapping work, i added this line after the above in context.startup():

mediatorMap.mapView(MultiTextViewerBase,MultiTextViewerMediator);
mediatorMap.mapView(StartPage, MultiTextViewerMediator);

When starting the app (which always adds a StartPage to the displaylist ;) ) I recieved "error-swiftsuspenders-viewBase-in-Mediator" (see the attached file)

to exclude if there is an error when a mediator is mapped twice i uncommented the fist of the two lines in context.startup().

//mediatorMap.mapView(MultiTextViewerBase,MultiTextViewerMediator);
mediatorMap.mapView(StartPage, MultiTextViewerMediator);

but it threw the same error.

The only solution left, I could think of right now was to change the class of view in MultiTextViewerMediator to StartPage.

[Inject]
public var view:StartPage;

Even if this does not solve my problem, because I wanted to map one mediator to multiple component-implementations (ideally without naming the concrete class(es), but naming it(them) to map to a more specific mediator when I want to), this removed the error-message and (of course) did the mapping and injection / onRegister as usual.

Is, could or will there be any way to do what I wan't?

Thx for help, karfau

  1. Support Staff 2 Posted by Shaun Smith on 21 Oct, 2009 08:59 PM

    Shaun Smith's Avatar

    Hi Karfau,

    I think I see what you're getting at. Could you build a tiny example app (smallest possible) that exhibits this same behavior - that would really help us determine the nature of the problem.

    Many thanks,
    Shaun

  2. 3 Posted by System on 21 Oct, 2009 09:02 PM

    System's Avatar

    An internal ticket was created for this discussion

  3. 4 Posted by karfau on 21 Oct, 2009 10:24 PM

    karfau's Avatar

    Here u go.

    Should my attempt work or does it need to be implemented?

    (the zipfile only contains the source, using RL v0.95)

    It uses FlexSDK 4 (i don't think thats a problem?)

    To get the errormessage uncomment lines 13+14 and comment out line 17+18 in view.BasicMediator.

  4. Support Staff 5 Posted by Shaun Smith on 21 Oct, 2009 11:18 PM

    Shaun Smith's Avatar

    Ah! Currently mediators can only be mapped to concrete view classes.
    This is for performance. We could look into enabling mapping to
    abstract classes as a framework addon, but the performance cost is
    going to be pretty substantial. I hope that's not too disapointing -
    I've been pondering this issue for some time myself.

    Shaun Smith
    http://shaun.boyblack.co.za

    On 22 Oct 2009, at 12:24 AM, karfau <[email blocked]
     > wrote:

  5. Support Staff 6 Posted by Till Schneidereit on 22 Oct, 2009 11:15 AM

    Till Schneidereit's Avatar

    Hey Karfau,

    I've thought about that issue quite extensively, too. Unfortunately,
    Shaun is absolutely right: There's no solution that would have
    acceptable performance for this problem.

    To give you a quick impression of what we would have to do, here's
    what happens now for every view that's added to the display list:

    - get the class name through reflection (and cache it after first retrieval)
    - make a lookup in our mediator mapping table to see if a mediator is
    mapped for that (concrete) view class
    - create the mediator if it has been found

    And here's what we'd have to do for your use case to work:

    - get the class name, all super class names and all implemented
    interfaces through reflection (and cache that, but much less
    efficiently)
    - make a lookup in our mediator mapping table for _each_ of these
    class names and interfaces
    - create the mediator if it has been found

    Keeping in mind that all of that has to be done for absolutely each
    view that's added to the display list, I guess you understand why
    that's a performance problem.

    cheers,
    till

  6. 7 Posted by karfau on 22 Oct, 2009 09:58 PM

    karfau's Avatar

    thx for this longer explanation.
    Im sure I just don't have any idea of how this works/ is implemented.

    But I have a small hope left, that I could get the small addition to the current solution, because my problem is not, that I don't want to map my concrete view (that would be great, but somehow lazy). I would love to map all concrete view-classes that can be handles by ONE Mediator-class (BasicMediator in my ExampleApp), if in this BasicMediator I could make the type the view-component to ViewComponentBase.

    So I think (when I look at the errormessage) that my problem is the injection that is not working, because it doesn't find the class to inject. But if the injector (not sure if I name the parts right here) would change the finding of the given viewComponent(vc) to inject for a property(p) from an

    classOf(vc)==classOf(p)

    to an

    vc is classOf(p)

    this would make me happy.

    Is this understandable? (I hope)
    possible (because some kind of new idea)? (I fear not)

    This will be my last attempt in this direction I think.

    Just for testing if I have understood u right:
    Another approach would be not to do this heavy stuff for(/at) all viewComponents/mediators but only if requested, like in:
    mediatorMap.mapGenericView( concreteViewComponentClass:*, mediatorClass:Class, genericAttributeClassOfViewComponentInMediator:*, auto...);

    e.g.(again with classes from my example-project)
    mediatorMap.mapGenericView( ViewComponentImpl, ViewComponentBaseMediator, ViewComponentBase);

    and would this still be heavy stuff? as it is not like

    • get the class name, all super class names and all implemented interfaces through reflection (and cache that, but much less
      efficiently)
    • make a lookup in our mediator mapping table for each of these class names and interfaces

    but names a concrete class to map?

    (I can still imagine thatt this is not needed "enough" to make the efford if this would require much code to change. But maybe this is a way to not make the mapping generic but only make the mediator generic.)

    So if all of this doesn't work, I need to copy the code of the ViewCompoenteBaseMediator into multiple classes and change the type of the viewComponent to the implementations and map all of these?

    wow, still a lot of questions, thx for the support so far,

    karfau

  7. Support Staff 8 Posted by Shaun Smith on 22 Oct, 2009 10:35 PM

    Shaun Smith's Avatar

    Aha! That you can do:

    mediatorMap.mapModule("view::ViewComponentImpl", ViewComponentBase,
    BasicMediator );
    mediatorMap.mapModule("view::ViewComponentImpl2", ViewComponentBase,
    BasicMediator );

    The first param (the Fully Qualified Class Name, or FQCN - note the
    "::") is used for the concrete mapping, the second param is what is
    injected on Mediator registration.

    Hope that helps!

    Cheers,
    Shaun

  8. 9 Posted by karfau on 22 Oct, 2009 10:40 PM

    karfau's Avatar

    ok, im not using modules, but this also works with normal viewcomponents?

    I will test if this does what i want on monday.

    thx, and cu

  9. Support Staff 10 Posted by Shaun Smith on 22 Oct, 2009 10:54 PM

    Shaun Smith's Avatar

    Yes, it is badly named I think, but it works with normal view
    components. I tested it out on the code you sent me and it works, so
    hopefully it's what you were looking for.

    cheers,

  10. 11 Posted by karfau on 22 Oct, 2009 11:02 PM

    karfau's Avatar

    Couldn't wait to see if it works the way I want: tested it right now:
    Jippie, thats what I wanted!!!

    by the way this:
    mediatorMap.mapModule( getQualifiedClassName(StartPage), MultiTextViewerBase, MultiTextViewerMediator); also works and is typesafe ;)

    (So I aks myself: how could I have asked to get this answer in the start ;) )

    (double) thx, karfau

  11. Support Staff 12 Posted by Shaun Smith on 22 Oct, 2009 11:14 PM

    Shaun Smith's Avatar

    Awesome! Glad to hear it :)

    Cheers,
    Shaun

  12. Support Staff 13 Posted by Till Schneidereit on 23 Oct, 2009 12:25 PM

    Till Schneidereit's Avatar

    Wow, that's actually something I didn't know as well. Immediate
    dramatic increase in usefulness of mapModule for me!

  13. Support Staff 14 Posted by Shaun Smith on 23 Oct, 2009 05:28 PM

    Shaun Smith's Avatar

    Yeh, mapModule is REALLY badly named.. has nothing to do with Flex
    modules.. dealing with Flex modules was just the first place I needed
    it :)

  14. Ondina D.F. closed this discussion on 29 Aug, 2012 09:16 AM.

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