tag:robotlegs.tenderapp.com,2009-10-18:/discussions/problems/107-adapting-own-framework-to-robotlegsRobotlegs: Discussion 2013-04-28T10:01:15Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T15:09:11Z2010-06-10T15:09:11ZAdapting own Framework to RobotLegs<div><p>Robotlegs doesn't make using singleton views easy, that's true.
But<br>
that's also something you should try to avoid if at all
possible.</p>
<p>Without knowing the specifics of your setup, it sounds to me
like the<br>
easiest way to adapt your architecture would be to introduce a<br>
singleton view registry with which you can register your views.
Then<br>
mediate the "singleton" views as all others but register them with
the<br>
registry over which they can be accessed by all interested
parties.</p>
<p>Mapping a Context (or whatever else) class as a singleton is as
easy as<br>
injector.mapSingleton(Context);</p></div>Till Schneidereittag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T15:43:52Z2010-06-10T15:43:52ZAdapting own Framework to RobotLegs<div><p>Thanks a lot for the explanation! If I think about it there's
only really one view class that was a Singleton which happens to be
a (debug) console class to that logging output is sent. I suppose
it wouldn't hurt too much to not map it as a Singleton but instead
create a Mediator for it?!</p>
<p>About the Singleton Context ... I have a class named Main which
is my Context. I've mapped it with:</p>
<p>injector.mapSingleton(Main);</p>
<p>... inside the Main class' startup() and injected it into a view
class that has a mediator mapped to it. Now in the mediator I'm
trying to access a property of the Main class (in the view class I
can't /shouldn't inject Main if I see that right?) but if I try
that I get the following exception:</p>
<p>InjectorError: Injector is missing a rule to handle injection
into target [class Main]. Target dependency: flash.display::Sprite,
method: constructor, parameter: 1</p>
<p>The Main class constructor has a parameter of type Sprite (which
becomes the contextView). Any ideas?</p></div>saschatag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T17:10:14Z2010-06-10T17:10:14ZAdapting own Framework to RobotLegs<div><p>You should create a mediator for that debug console, right.
Maybe<br>
create an accompanying DebugConsoleModel which you register the<br>
mediator with or something similar.</p>
<p>The reason for your singleton mapping of Main not working is
that the<br>
injector can't construct the singleton instance. That's because
it<br>
doesn't know how to supply the dependency your Main class's<br>
constructor has: the Sprite. To make it work, you can do one of
two<br>
things:</p>
<ol>
<li>
<p>create the instance eagerly in your startup method, supplying
the<br>
contextView manually. Then you can use mapValue, resulting in
that<br>
same value being returned each time the type Main is required
for<br>
injection.</p>
</li>
<li>
<p>change the type your Main class's constructor expects to<br>
DisplayObjectContainer - that's the type by which the contextView
is<br>
mapped by default.</p>
</li>
</ol></div>Till Schneidereittag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T17:43:14Z2010-06-10T17:43:14ZAdapting own Framework to RobotLegs<div><p>Ok I've tried your second suggestion, changing the constructor
argument to type DisplayObjectContainer but instead of the former
error I'm now getting a Stack Overflow Exception.</p>
<p>About solution Nr. 1 ... but actually the Main class is already
existing. I map it (as mentioned above) to Singleton inside its own
startup() method and the view class. This is how my Main class
looks:</p>
<p>` public class Main extends Context<br>
{</p>
<pre>
<code>private var _config:Config;
private var _applicationUI:ApplicationUI;
public function Main(app:DisplayObjectContainer)
{
super(app, true);
}
override public function startup():void
{
_config = new Config();
injector.mapSingleton(Main);
mediatorMap.mapView(ApplicationUI, ApplicationUIMediator);
_applicationUI = new ApplicationUI();
contextView.addChild(_applicationUI);
super.startup();
}
public function get config():Config
{
return _config;
}</code>
</pre>
<p>} `</p>
<p>And here's my view mediator:</p>
<p>` public class ApplicationUIMediator extends Mediator<br>
{</p>
<pre>
<code>[Inject]
public var _main:Main;
[Inject]
public var _applicationUI:ApplicationUI;
override public function onRegister():void
{
super.onRegister();
trace(_main.config.consoleKey);
}</code>
</pre>
<p>} `</p></div>saschatag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T17:56:56Z2010-06-10T17:56:56ZAdapting own Framework to RobotLegs<div><p>Aha, I didn't understand that Main is extending Context!</p>
<p>In that case, just use<br>
injector.mapValue(Main, this);</p></div>Till Schneidereittag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T18:18:49Z2010-06-10T18:18:49ZAdapting own Framework to RobotLegs<div><p>Ok that did it! Even though Main is now not mapped as a
Singleton anymore. But I guess I can live with that.</p>
<p>Thanks for your time and help! :)</p></div>saschatag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-10T20:54:33Z2010-06-10T20:54:33ZAdapting own Framework to RobotLegs<div><p>Main is effectively mapped as a context managed Singleton.
Unless you override that mapping later, only the one instance is
available for injection.</p></div>Joel Hookstag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-11T02:59:57Z2010-06-11T02:59:57ZAdapting own Framework to RobotLegs<div><p>Good to know that, thanks Joel! I was wondering if Context
classes get a special treatment like that.</p></div>saschatag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-11T10:13:34Z2010-06-11T10:13:34ZAdapting own Framework to RobotLegs<div><p>I'm not sure you're saying that, but just to make sure:
Context<br>
doesn't get any special treatment at all. In fact, no other class
in<br>
the framework even knows about or ever even gets a reference to
the<br>
context - it's just something similar to a main entry point that
kicks<br>
things off.</p>
<p>What actually happens is that mapValue causes the injector to
always<br>
return that same value for each request. That means that
ultimately,<br>
mapValue works the same as mapSingleton does, with the only
difference<br>
being that singleton mappings don't create the singleton
instance<br>
until it is actually requested for the first time.</p></div>Till Schneidereittag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-11T12:09:37Z2010-06-11T12:22:08ZAdapting own Framework to RobotLegs<div><p>Yes, I didn't want to imply that a Context get's a special
treatment as in "being treated as a Singleton". i guess my quote
above is misleading.</p>
<p>I got another small question: How do I inject a static class? I
have one class which has only static methods and in this class I
need access to two other classes which are mapped. I injected these
two in the static class as static properties but how do I get RL to
map the static class?</p></div>saschatag:robotlegs.tenderapp.com,2009-10-18:Comment/19195512010-06-11T15:08:36Z2010-06-11T15:08:36ZAdapting own Framework to RobotLegs<div><p>You can neither inject into static fields of a class, nor can
you map<br>
the class itself to anything but "Class". The first of these
you<br>
should not do anyway: Static state should be avoided if in any
way<br>
possible at all. The second just doesn't work. For example,
"MyClass"<br>
is an instance of the class "Class", so all you could do would be
to<br>
use injector.mapValue(Class, MyClass), but I guess that's not what
you<br>
imagined.</p>
<p>I would recommend changing your class to not use static state
and<br>
methods and inject an instance of it using mapSingleton or
mapValue.</p>
<p>If you've got any further questions about this, please open a
new<br>
topic, as this is really unrelated to the topic discussed here<br>
earlier. Thus, I'm closing this thread now.</p></div>Till Schneidereit