Extend Mediators

Roland's Avatar


14 Jan, 2010 06:01 PM

Hi everybody.
I was wondering how I could extend Meditors.
Just a simple example:

  • I've got a site-engine which creates the single sites during runtime with the use of factory pattern. This means that I am creating a site object of type ISite in a controller and fire an event with this object as body. Then I simply add this object as a child of my site holder with the type Site
  • every site is extending the Site class and implements the ISite interface
  • every site has some basic communication with their mediators, but some sites do have an extended mediator communication

I want to implement one mediator, for example »SiteMediator«, which maps basic events of the view. But for some special sites I want a mediator which handles more events but the basic events as well. So I thought I could extend my »SiteMediator« and make a new mediator called »SpecialSiteMediator«.

I injected the view as »Site« in »SiteMediator« and the view as »SpecialSite« in »SpecialSiteMediator«. This does not work because of the redundant declaration of the property »view«. Injection the view only in »SiteMediator« as »Site« will cause this error »Error: Injector is missing a rule to handle injection into target [object SpecialSiteMediator]. Target dependency: com....::SiteMediator.as «

I hope you are able to understand the problem.

Thank you very much.


  1. 1 Posted by Roland on 14 Jan, 2010 06:04 PM

    Roland's Avatar

    Sorry, could you please move this to »Problems«.... Thank you.

  2. 2 Posted by levi.strope on 14 Jan, 2010 08:49 PM

    levi.strope's Avatar

    Hi Roland,

    I could be completely off base with this solution but I'd love to be corrected.

    I believe your problem is because you are trying to use an injected property of a super class in your concrete class specialsitemediator. In your case they are both concrete classes but you are treating sitemediator as an abstract.

    I do believe Robotlegs cannot inject into superclasses and have it available in your concrete class; you must define the dependency in your concrete class. My understanding of this is because it would cause far too much overhead to try to provide DI to non-concrete classes.

    Essentially, you can extend your mediator but I believe your superclass should extend MediatorBase and then you could possibly define your view injection and then extend that class - I think that would work. But extending a class that extends mediator will not.

    Essentially I think you need to roll your own mediator class and not use robotlegs MVCS implementation of Mediator.

    Does that make sense?

    Check out this cheat sheet. http://andreitt.com/robotlegs/diagram/update/robotlegs_cheatsheet2.jpg

    Here is what Mediator looks like:
    package org.robotlegs.mvcs

    import flash.display.DisplayObjectContainer;
    import flash.events.Event;
    import flash.events.IEventDispatcher;
    import org.robotlegs.base.EventMap;
    import org.robotlegs.base.MediatorBase;
    import org.robotlegs.core.IEventMap;
    import org.robotlegs.core.IMediatorMap;
     * Abstract MVCS <code>IMediator</code> implementation
    public class Mediator extends MediatorBase
        public var contextView:DisplayObjectContainer;
        public var mediatorMap:IMediatorMap;
         * @private
        protected var _eventDispatcher:IEventDispatcher;
         * @private
        protected var _eventMap:IEventMap;
        public function Mediator()
    //The rest left out for brevity, I think you get the point here.

    (whats a good word for non-concrete classes?)

  3. 3 Posted by Roland on 14 Jan, 2010 09:31 PM

    Roland's Avatar

    Hi levi.
    Thank you for your answer.
    When I tell the truth, I don't know what my custom mediator should look like or what I would change on the existing robot legs mediator.
    If I only inject the view in my concrete class specialsitemediatorand not in its superclass sitemediator there is the problem, that I'm not able to map any events to the view in the superclass neither call functions of it. Maybe I got you wrong, but I need the injection of the view-superclass 'site' in the mediator-superclass 'sitemediator' and the view-concreteclass 'specialsite' in the mediator-concreteclass 'specialsitemediator' to map events and call functions.

    Sorry if I'm on the wrong track.

  4. 4 Posted by rw on 22 Jan, 2010 02:55 PM

    rw's Avatar

    I think I had the same problem. This is what I used for my solution. In my AbstractMediator, I had public var view:IView (has to be an interface). So When I map the view it Looks like this:

    mediatorMap.mapView(View, Mediator, IView);

    instead of

    mediatorMap.mapView(View, Mediator, View);

    So in the super Mediator you can access the view after the onRegister().

  5. 5 Posted by Roland on 22 Jan, 2010 03:00 PM

    Roland's Avatar

    Perfect. Thank you very much for your answer. I will check this as soon as possible and post the result right here.

    Thanks again.


  6. 6 Posted by Roberto on 11 Feb, 2010 06:20 PM

    Roberto's Avatar

    Hi guys,

    I'm trying to do something similar, injecting a concrete class reference to its interface type, but with no success.

    I defined a DataLoadCommand class.
    In this class I have an injectedModel of type IMyModel
    and an injectedEvent of type IDataRequestEvent. Let's speak about this.

    In the AppContext I'm trying to map that injection using the injector with:
    injector.mapValue(IDataRequestEvent, DataRequestEvent);
    I'm using mapValue as the (concrete) DataRequestEvent is instantiated and dispatched from inside the mediator.
    I think there is something wrong or I'm missing.

    What I'm traying to do would be something like:

    inject into SpecificDataLoadCommand, 
    the reference to DataRequestEvent, 
    where you find the type IDataRequestEvent

    but I don't know how to do that...

    Am I missing something?
    Is it possible to inject a concrete class (reference) to its interface type with Robotlegs ioc?

    Thanks a lot

  7. Support Staff 7 Posted by Till Schneidere... on 11 Feb, 2010 06:58 PM

    Till Schneidereit's Avatar

    Hi Roberto,

    unfortunately, what you're trying to do isn't possible with Robotlegs.

    The injector mapping for an event class to be injected into a command
    is created dynamically by the framework during event dispatch; there's
    no other way to inject the short-lived event instances.
    Internally, Robotlegs looks up the type for each event and creates a
    temporary mapping between that type and the current instance of the
    event like so:
    var eventClass : Class = event['constructor'];
    injector.mapValue(eventClass, event);
    var command : Object = injector.instantiate(commandClass);

    To be able to inject as an interface type, Robotlegs would need to
    know about all possible interfaces the event could be injected as and
    would have to create temporary mappings for all of them. That isn't
    only impractical, it'd also be dangerous: An event might (for whatever
    reason) implement an interface that's already mapped in the injector.
    That mapping would then be overwritten.

    What your mapping does is to instruct the injector to return the
    *class* DataRequestEvent when asked for the interface
    IDataRequestEvent. You're probably getting a type error on injection,
    right? This is because the Flashplayer is trying to convert the class
    to an instance, which naturally fails.

    hope that helps,

  8. 8 Posted by Roberto on 11 Feb, 2010 09:10 PM

    Roberto's Avatar

    Hi tschneidereit,

    thanks for your help.

    Ok I understand the point even if I'd like to clarify that my idea is not to inject an interface but a reference to a class that implements that interface.

    So for example I have something like:

    [Inject] public var injectedEvent:IDataRequestEvent;

    in the context mapping I will say that in the class DataLoader (for example) the member variable injectedEvent has to be injected with the reference to the concrete class DataRequestEventImpl (for example). I understand maybe it is wrong in this picture to talk about events as they are short lived etc.

    Yes as you say I get a type error for a cast that (the flash player) tries to achieve but more than a cast it would be a promotion from a derived type to the base one. Isn't it?

    Thanks again

  9. Support Staff 9 Posted by Till Schneidere... on 11 Feb, 2010 09:22 PM

    Till Schneidereit's Avatar

    If you want to inject instances as the interface type for long-lived
    objects, you can do that by using the various mapping methods of

    Right now, what you're trying fails because you're using mapValue, but
    then supply a class as the value to be injected. Depending on your
    exact usecase, you might want to use either

    - mapClass - which creates a new instance for each injection:
    injector.mapClass(IMyInterface, MyClass);
    - mapSingleton - which creates one instance on the first injection and
    then reuses that for subsequent one:
    injector.mapSingletonOf(IMyInterface, MyClass);
    - mapValue with an instance instead of a class
    injector.mapValue(IMyInterface, new MyClass());

    In all cases, you can specify an interface that the mapped value
    implements and specify your dependencies as being of that interface

    If you absolutely must use this for events, you could create your own
    temporary mapping while dispatching the event. Instead of
    dispatch(new MyEvent(MyEvent.MY_EVENT_TYPE));
    you'd write
    var event : MyEvent = new MyEvent(MyEvent.MY_EVENT_TYPE);
    injector.mapValue(IMyEventInterface, event); //temporarily map the
    event to the interface
    injector.unmap(IMyEventInterface); //remove the temporary mapping

  10. 10 Posted by Roberto on 12 Feb, 2010 09:42 AM

    Roberto's Avatar

    Ok. Thanks!

  11. Till Schneidereit closed this discussion on 12 Feb, 2010 10:29 AM.

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

Keyboard shortcuts


? 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