Nested Injection with MXML

2 views
Skip to first unread message

Tim Mead

unread,
Dec 22, 2008, 11:49:38 PM12/22/08
to Smartypants IOC
This might be a misunderstanding on my behalf, or an inadvertent
feature request. Let's say we have an MXML application, which uses a
custom MXML component that has certain fields tagged with the inject
annotation, and the application defines the injection rules, and
requests the injection - is it possible, or will it be possible, for
the injection to be automatically performed in the aforementioned MXML
component. That is, given:

-----------------------------

TestApplication.mxml :

<mx:Application preinitialize="preInit()">

<mx:Script>
<![CDATA[

import net.expantra.smartypants.SmartyPants;
import net.expantra.smartypants.Injector;

private function preInit()
{
var i:Injector = SmartyPants.getOrCreateInjectorFor(this);

i.newRule().whenAskedFor(IBar).useSingletonOf(Bar);

i.injectInto(this);
}

]]>
</mx:Script>

<local:CustomComponent />

</mx:Application>

CustomComponent.mxml :

<mx:Canvas>

<mx:Script>
<![CDATA[

[Inject]
public var foo:IBar;

]]>
</mx:Script>

</mx:Canvas>

--------------------------

I would expect the variable 'foo' in the instance of CustomComponent
to be populated using the concrete class Bar.

Cheers!
- Tim

Josh McDonald

unread,
Dec 23, 2008, 1:56:57 AM12/23/08
to smartyp...@googlegroups.com
If you're injecting CustomComponent, it'll obviously be taken care of. However if you're instantiating it via an mxml tag, just add the <smartypants:RequestInjection/> tag to CustomComponent.mxml, and it will hook into CreationComplete and call SmartyPants.locateInjectorFor(myComponentInstance).injectInto(myComponentInstance) on your behalf.

-Josh
--
"Therefore, send not to know For whom the bell tolls. It tolls for thee."

Like the cut of my jib? Check out my Flex blog!

:: Josh 'G-Funk' McDonald
:: 0437 221 380 :: jo...@gfunk007.com
:: http://flex.joshmcdonald.info/
:: http://twitter.com/sophistifunk

Tim Mead

unread,
Dec 23, 2008, 9:28:11 PM12/23/08
to Smartypants IOC
Thanks for the tip Josh.

I did try adding a <smartypants:RequestInjection/> to
CustomComponent.mxml, but that throws the following run-time error:

Error: Could not find an injector for
DependencyInjectionTest0.CustomComponent4
at net.expantra.smartypants::SmartyPants$/getInjectorFor()[/Users/
josh/Desktop/Work/Builder Workspace/smartypants_ioc/src/net/expantra/
smartypants/SmartyPants.as:44]
at net.expantra.smartypants::RequestInjection/cc()[/Users/josh/
Desktop/Work/Builder Workspace/smartypants_ioc/src/net/expantra/
smartypants/RequestInjection.as:24]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.2.0\frameworks
\projects\framework\src\mx\core\UIComponent.as:9298]
at mx.core::UIComponent/set initialized()[C:\autobuild
\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:1169]
at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild
\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:
718]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild
\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild
\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]

Any other tips? :)
> :: 0437 221 380 :: j...@gfunk007.com
> ::http://flex.joshmcdonald.info/
> ::http://twitter.com/sophistifunk

Josh McDonald

unread,
Dec 25, 2008, 7:35:08 PM12/25/08
to smartyp...@googlegroups.com
No worries, that problem is fixed in SVN I think. In the .swc version, RequestInjection requires that an injector be already created that is valid for the current mxml document (by going back up the display tree looking for an injector for an existing object). I'm hoping to write some more tests, implement a couple of features and have 1.0 ready in a week, as I've got some time off :)

You can work around it by simply creating an injector for your Application in the handler for preInitialize:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
                preinitialize="preInit()" creationComplete="cc()">

    <mx:Script>
        <![CDATA[

        private var injector : Injector;

        private function preInit() : void
        {
            //Create our injector
            injector = SmartyPants.getOrCreateInjectorFor(this);
        }

        private function cc() : void
        {
            //Inject stuff :)
            injector.injectInto(this);
        }

        ]]>
    </mx:Script>
</mx:Application>
Reply all
Reply to author
Forward
0 new messages