tag:robotlegs.tenderapp.com,2009-10-18:/discussions/questions/9382-where-and-when-does-the-injector-begin-constructionRobotlegs: Discussion 2015-05-11T11:32:55Ztag:robotlegs.tenderapp.com,2009-10-18:Comment/359802592015-02-06T10:32:17Z2015-02-06T10:32:18ZWhere and when does the injector begin construction?<div><p>I am reading the book ActionScript Developers guide to
robotlegs.<br>
There are example files here for a Mosaic tool:</p>
<p><a href=
"http://examples.oreilly.com/9781449308902-files/">http://examples.oreilly.com/9781449308902-files/</a></p>
<p>I don't understand where does the injector construct all these
models and services?<br>
It says, if an object has an [inject]ed dependency you have to
create it using the injector (I get this).</p>
<p>In here:<br>
<a href=
"https://github.com/robotlegs/robotlegs-framework/wiki/Robotlegs-Internals">
https://github.com/robotlegs/robotlegs-framework/wiki/Robotlegs-Int...</a></p>
<p>It says you can use the syntax injector.getInstance(...);</p>
<p>I am working to learn from the books Mosaic tool example but I
don't see or understand where the construction done by the injector
normally happens. The examples show the mapping but I don't get
where the actual construction is occurring.</p>
<p>I could use some pointers. :)</p></div>Arthurtag:robotlegs.tenderapp.com,2009-10-18:Comment/359802592015-02-06T15:54:03Z2015-02-06T15:54:04ZWhere and when does the injector begin construction?<div><p>To clarify:</p>
<p>In code where I don't use a framework, I would do something like
this:</p>
<p>var someController = new SomeController(someDependency,
someOtherDependency);</p>
<p>Now with Robotlegs I do something like:</p>
<p>mapSingletonOf(IDependency, SomeDependency);<br>
mapSingletonOf(IOtherDependency, SomeOtherDependency);</p>
<p>Now obviously, if I do:<br>
var controller = new SomeController(); // The "magic" injection
does not happen</p>
<p>In the code example I've seen (Mosaic):</p>
<p>override public function startup():void<br>
{ new BootstrapConfigValues(injector); // Used to define defaults
for several values new BootstrapModels(injector); // Used to
structure the data that is manipulated by the application new
BootstrapServices(injector); // Mainly used to save and load files
- can be used to communicate with a database and/or a server new
BootstrapCommands(commandMap); // These are one liners that do
things when events happen new
BootstrapTileSupplyCommands(commandMap); new
BootstrapClasses(injector); new
BootstrapViewMediators(mediatorMap);</p>
<pre>
<code> addRootView();
// and we're done
super.startup();
}</code>
</pre>
<p>Inside BootstrapModels(injector);</p>
<pre>
<code> public function BootstrapModels(injector:IInjector)
{
injector.mapSingletonOf(IConfigModel, ConfigModel);
injector.mapSingletonOf(IMosaicDesignModel, MosaicDesignModel);
injector.mapSingletonOf(ITileSuppliesModel, TileSuppliesModel);
injector.mapSingletonOf(IMosaicSpecModel, MosaicSpecModel);
injector.mapSingletonOf(IAutoIncrementor, AutoIncrementor);
}</code>
</pre>
<p>So this is where the injection is setup.</p>
<p>But when and where and why are the models constructed?<br>
I don't understand how the part that tell the injector to construct
all these models gets invoked.</p>
<p>Thanks,</p>
<p>Arthur</p></div>Arthurtag:robotlegs.tenderapp.com,2009-10-18:Comment/359802592015-02-09T17:32:14Z2015-02-09T17:32:14ZWhere and when does the injector begin construction?<div><p>Hi Arthur,</p>
<p>I just got home from a week-long conference and I'm pretty
tired. I'll try to answer your questions in the next days, if no
one else will :)</p>
<p>Ondina</p></div>Ondina D.F.tag:robotlegs.tenderapp.com,2009-10-18:Comment/359802592015-02-10T18:10:05Z2015-02-10T18:10:05ZWhere and when does the injector begin construction?<div><blockquote>
<p>In code where I don't use a framework, I would do something like
this: var someController = new SomeController(someDependency,
someOtherDependency);</p>
</blockquote>
<p>Right. And it reads like this: Arthur is instantiating
SomeController and is 'injecting' its dependencies using the
constructor. Arthur knows about SomeController and what it needs to
do its work, i.e. someDependency, someOtherDependency. If
someDependency and someOtherDependency are not optional and Arthur
forgets to pass them as arguments when he is constructing
SomeController, something bad will happen ;)<br>
If SomeController is needed in more than one class, Arthur needs to
instantiate it every time and to provide its dependencies.</p>
<blockquote>
<p>It says, if an object has an [inject]ed dependency you have to
create it using the injector (I get this).</p>
</blockquote>
<p>That's indeed the first step in understanding how injection
works. If the Injector is the one who has to provide a class with
its dependencies, it has to instantiate that class itself, or to
know in some way that that class needs injection (see below) !</p>
<blockquote>
<p>Now with Robotlegs I do something like:
mapSingletonOf(IDependency, SomeDependency);<br>
mapSingletonOf(IOtherDependency, SomeOtherDependency);<br>
Now obviously, if I do:<br>
var controller = new SomeController(); // The "magic" injection
does not happen</p>
</blockquote>
<p>Yes, because the Injector won't inspect <strong>every</strong>
class in our code to see if there is a need for a dependency. The
Injector will only look inside classes that are
<strong>known</strong> to it.</p>
<p>When and how does the Injector find out that a class/object
needs injection?<br>
The moment it (the Injector) instantiates the class or if you
explicitly tell it to injectInto that class (see further down).</p>
<p>How? By looking at the <strong>injection points</strong> . The
most used injection point is in form of property injection. If the
Injector finds a property annotated with an [Inject] metatag inside
of a class, it tries to instantiate that object/class.</p>
<p>So, if you had<br>
[Inject] public var someDependency:IDependency; inside of
SomeController, the Injector is unaware of its existence, because
it doesn't even know that SomeController is there.</p>
<p>When does the Injector instantiate a class?<br>
The keyword is <strong>ON DEMAND</strong>.<br>
<strong>The Injector instantiates classes only on
request.</strong></p>
<p>The request can be explicit like in:</p>
<pre>
<code>injector.instantiate(SomeController);</code>
</pre>
<p>or</p>
<pre>
<code>injector.mapSingleton(SomeController);
injector.getInstance(SomeController);</code>
</pre>
<ul>
<li>
<p>"instantiate" is used to create an instance of a given class,
regardless of whether or not there is a rule for such a class in
the container. As such, it must be handed a class, not an
interface, and it will always create a new instance. It is used by
the CommandMap to create new command instances.</p>
</li>
<li>
<p>"getInstance", on the other hand, can be handed a class,
abstract class, or interface, and it will return an instance based
on a previously mapped rule. As such, a rule must exist or an error
will be thrown. Also, multiple calls to "getInstance" might return
the same instance, whereas "instantiate" will always return a new
instance.</p>
</li>
</ul>
<p>However, you can tell the Injector to inject IDependency and
IOtherDependency into an instance of SomeController that you
created yourself like so:</p>
<pre>
<code>mapSingletonOf(IDependency, SomeDependency);
mapSingletonOf(IOtherDependency, SomeOtherDependency);
var controller = new SomeController();
injector.injectInto(controller);</code>
</pre>
<blockquote>
<p>But when and where and why are the models constructed? I don't
understand how the part that tell the injector to construct all
these models gets invoked.</p>
</blockquote>
<p>By now, you know that the Injector is constructing classes only
on request. The request can be<br>
getInstance() or the [Inject] metatag.<br>
When the Injector encounters an [Inject] the following happens
(simplified):</p>
<ul>
<li>it instantiates the class (see <a href=
"https://github.com/robotlegs/swiftsuspenders/blob/the-past/src/org/swiftsuspenders/Injector.as#L130">
https://github.com/robotlegs/swiftsuspenders/blob/the-past/src/org/...</a>)</li>
<li>it looks at the injection points in this class</li>
<li>it checks for the existence of a rule for that class, in order
to know <strong>how</strong> to inject it ( mapClass, mapValue,
mapSingleton)</li>
<li>runs injectionPoint.applyInjection(clazz, this);</li>
<li>injectInto(target : Object) ( see <a href=
"https://github.com/robotlegs/swiftsuspenders/blob/the-past/src/org/swiftsuspenders/Injector.as#L107">
https://github.com/robotlegs/swiftsuspenders/blob/the-past/src/org/...</a>
)</li>
<li>InjectionConfig.getResponse(injector) == the object /
class</li>
</ul>
<p>I hope that's the right order in which things happen there. You
could follow the flow yourself by putting a few trace statements
inside those methods.</p>
<p>What triggers the construction/creation/instantiation of
classes? That depends on the class and on the flow you defined for
your application.<br>
As you know, mediators are created when views are added to the
stage.<br>
The creation of commands is triggered by events. Models are usually
injected into commands and services. So, if a model is injected
into a command, the moment that command is created, the Injector
will instantiate the model.<br>
So, if the first thing happening in your application is the
creation of a Mediator for the contextView, for example , the
MediatorMap will tell the injector to instantiate the Mediator:</p>
<pre>
<code>public function createMediator(viewComponent:Object):IMediator
{
var mediator:IMediator = mediatorByView[viewComponent];
if (mediator == null)
{
var viewClassName:String = getQualifiedClassName(viewComponent);
var config:MappingConfig = mappingConfigByViewClassName[viewClassName];
if (config)
{
injector.mapValue(config.typedViewClass, viewComponent);
mediator = injector.instantiate(config.mediatorClass);
injector.unmap(config.typedViewClass);
registerMediator(viewComponent, mediator);
}
}
return mediator;
}</code>
</pre>
<p>A command class is instantiated inside of the CommandMap.
routeEventToCommand()<br>
var command:Object = injector.instantiate(commandClass);</p>
<blockquote>
<p>But when and where and why are the models constructed?</p>
</blockquote>
<p>I hope that I answered the when and where. I don't know anything
about the why :P You tell me. Or, did you mean why the models were
constructed in the mosaictool example?</p>
<p>You could also take a look at these discussions:</p>
<p><a href=
"http://knowledge.robotlegs.org/discussions/robotlegs-2/5766-automagic-view-injection#comment_28759520">
http://knowledge.robotlegs.org/discussions/robotlegs-2/5766-automag...</a></p>
<p><a href=
"http://knowledge.robotlegs.org/discussions/robotlegs-2/8182-the-necessary-conditions-of-injection-to-work#comment_30057747">
http://knowledge.robotlegs.org/discussions/robotlegs-2/8182-the-nec...</a></p>
<p>Let me know whether I answered your questions or not.</p>
<p>Ondina</p></div>Ondina D.F.