tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/37-extend-mediatorsRobotlegs: Discussion 2018-10-18T16:35:08Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-01-14T18:04:32Z2010-01-14T18:04:32ZExtend Mediators<div><p>Sorry, could you please move this to »Problems«....
Thank you.</p></div>Rolandtag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-01-14T20:49:59Z2010-01-14T20:49:59ZExtend Mediators<div><p>Hi Roland,</p>
<p>I could be completely off base with this solution but I'd love
to be corrected.</p>
<p>I believe your problem is because you are trying to use an
injected property of a super class in your concrete class
<code>specialsitemediator</code>. In your case they are both
concrete classes but you are treating <code>sitemediator</code> as
an abstract.</p>
<p>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.</p>
<p>Essentially, you can extend your mediator but I believe your
superclass should extend <code>MediatorBase</code> 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.</p>
<p>Essentially I think you need to roll your own mediator class and
not use robotlegs MVCS implementation of Mediator.</p>
<p>Does that make sense?</p>
<p>Check out this cheat sheet. <a href=
"http://andreitt.com/robotlegs/diagram/update/robotlegs_cheatsheet2.jpg">
http://andreitt.com/robotlegs/diagram/update/robotlegs_cheatsheet2.jpg</a></p>
<p>Here is what Mediator looks like:<br>
package org.robotlegs.mvcs<br>
{</p>
<pre>
<code>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
{
[Inject]
public var contextView:DisplayObjectContainer;
[Inject]
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.</code>
</pre>
<p>(whats a good word for non-concrete classes?)</p></div>levi.stropetag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-01-14T21:31:32Z2010-01-14T21:31:35ZExtend Mediators<div><p>Hi levi.<br>
Thank you for your answer.<br>
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.<br>
If I only inject the view in my concrete class
<code>specialsitemediator</code>and not in its superclass
<code>sitemediator</code> 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.</p>
<p>Sorry if I'm on the wrong track.</p></div>Rolandtag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-01-22T14:55:46Z2010-01-22T14:55:47ZExtend Mediators<div><p>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:</p>
<p>mediatorMap.mapView(View, Mediator, IView);</p>
<p>instead of</p>
<p>mediatorMap.mapView(View, Mediator, View);</p>
<p>So in the super Mediator you can access the view after the
onRegister().</p></div>rwtag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-01-22T15:00:14Z2010-01-22T15:00:14ZExtend Mediators<div><p>Perfect. Thank you very much for your answer. I will check this
as soon as possible and post the result right here.</p>
<p>Thanks again.</p>
<p>Roland</p></div>Rolandtag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-02-11T18:20:54Z2010-02-11T18:20:58ZExtend Mediators<div><p>Hi guys,</p>
<p>I'm trying to do something similar, injecting a concrete class
reference to its interface type, but with no success.</p>
<p>I defined a DataLoadCommand class.<br>
In this class I have an injectedModel of type IMyModel<br>
and an injectedEvent of type IDataRequestEvent. Let's speak about
this.</p>
<p>In the AppContext I'm trying to map that injection using the
injector with:<br>
injector.mapValue(IDataRequestEvent, DataRequestEvent);<br>
I'm using mapValue as the (concrete) DataRequestEvent is
instantiated and dispatched from inside the mediator.<br>
I think there is something wrong or I'm missing.</p>
<p>What I'm traying to do would be something like:<br></p>
<pre>
<code>inject into SpecificDataLoadCommand,
the reference to DataRequestEvent,
where you find the type IDataRequestEvent</code>
</pre>
<p>but I don't know how to do that...</p>
<p>Am I missing something?<br>
Is it possible to inject a concrete class (reference) to its
interface type with Robotlegs ioc?</p>
<p>Thanks a lot<br>
Roberto</p></div>Robertotag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-02-11T18:58:03Z2010-02-11T18:58:03ZExtend Mediators<div><p>Hi Roberto,</p>
<p>unfortunately, what you're trying to do isn't possible with
Robotlegs.</p>
<p>The injector mapping for an event class to be injected into a
command<br>
is created dynamically by the framework during event dispatch;
there's<br>
no other way to inject the short-lived event instances.<br>
Internally, Robotlegs looks up the type for each event and creates
a<br>
temporary mapping between that type and the current instance of
the<br>
event like so:<br>
var eventClass : Class = event['constructor'];<br>
injector.mapValue(eventClass, event);<br>
var command : Object = injector.instantiate(commandClass);<br>
injector.unmap(eventClass);</p>
<p>To be able to inject as an interface type, Robotlegs would need
to<br>
know about all possible interfaces the event could be injected as
and<br>
would have to create temporary mappings for all of them. That
isn't<br>
only impractical, it'd also be dangerous: An event might (for
whatever<br>
reason) implement an interface that's already mapped in the
injector.<br>
That mapping would then be overwritten.</p>
<p>What your mapping does is to instruct the injector to return
the<br>
<em>class</em> DataRequestEvent when asked for the interface
IDataRequestEvent. You're probably getting a type error on
injection,<br>
right? This is because the Flashplayer is trying to convert the
class<br>
to an instance, which naturally fails.</p>
<p>hope that helps,<br>
till</p></div>Till Schneidereittag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-02-11T21:10:26Z2010-02-11T21:10:29ZExtend Mediators<div><p>Hi tschneidereit,</p>
<p>thanks for your help.</p>
<p>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.</p>
<p>So for example I have something like:</p>
<p>[Inject] public var injectedEvent:IDataRequestEvent;</p>
<p>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.</p>
<p>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?</p>
<p>Thanks again<br>
R.</p></div>Robertotag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-02-11T21:22:56Z2010-02-11T21:22:56ZExtend Mediators<div><p>If you want to inject instances as the interface type for
long-lived<br>
objects, you can do that by using the various mapping methods
of<br>
IInjector.</p>
<p>Right now, what you're trying fails because you're using
mapValue, but<br>
then supply a class as the value to be injected. Depending on
your<br>
exact usecase, you might want to use either</p>
<ul>
<li>mapClass - which creates a new instance for each injection:
injector.mapClass(IMyInterface, MyClass);<br></li>
<li>mapSingleton - which creates one instance on the first
injection and then reuses that for subsequent one:<br>
injector.mapSingletonOf(IMyInterface, MyClass);<br></li>
<li>mapValue with an instance instead of a class
injector.mapValue(IMyInterface, new MyClass());</li>
</ul>
<p>In all cases, you can specify an interface that the mapped
value<br>
implements and specify your dependencies as being of that
interface<br>
type.</p>
<p>If you absolutely must use this for events, you could create
your own<br>
temporary mapping while dispatching the event. Instead of<br>
dispatch(new MyEvent(MyEvent.MY_EVENT_TYPE));<br>
you'd write<br>
var event : MyEvent = new MyEvent(MyEvent.MY_EVENT_TYPE);<br>
injector.mapValue(IMyEventInterface, event); //temporarily map
the<br>
event to the interface<br>
dispatch(event);<br>
injector.unmap(IMyEventInterface); //remove the temporary
mapping</p></div>Till Schneidereittag:robotlegs.tenderapp.com,2009-10-18:Comment/8552072010-02-12T09:42:24Z2010-02-12T09:42:27ZExtend Mediators<div><p>Ok. Thanks!</p></div>Roberto