Simple example of using SmartyPants

6 views
Skip to first unread message

Borek

unread,
Apr 27, 2009, 2:02:23 PM4/27/09
to Smartypants IOC
SmartyPants IOC looks good to me because it uses ActionScript to
define rules (I don't like XML configuration at all). However, I was
not able to find an example of what I would use DI primarily for:
injecting a service. Can someone post an example of an application
that would do something like the following:

* There is a Presenter that has a dependency on ICustomerService
* There is an implementation of CustomerService that can return an
ArrayCollection of Customer object. For the sake of simplicity, let's
ignore asynchronous nature of Flex network access.
* Presenter can store the value into a Model object
* View can then display the collection of Customers in a grid

I am most interested in the dependency injection on the Presenter/
Service layer. How do you inject that dependency? In what object will
the rule definitions live? Where do I get the instances from the IoC
container?

It would be much appreciated,
thanks,
Borek

Josh McDonald

unread,
Apr 27, 2009, 6:53:53 PM4/27/09
to smartyp...@googlegroups.com
Hi Borek,

Normally, you request to have fields injected using the [Inject] metadata, like so:

public class Injectee
{
    [Inject]
    public var service:ICustomerService;
}

And you specify your rules as part of your application bootstrap using the DSL:

function buildRules():void
{
    // ...
    SmartyPants.whenAskedFor(ICustomerService).useSingletonOf(CustomerServiceImpl);
    // ...
}

So now, when the injector builds an instance of Injectee, it will inject the correct service impl for you.

If your dependant object is constructed via MXML instead of by the injector, you can use the <smartypants:RequestInjection/> tag, which will register an event listener for CREATION_COMPLETE and call SmartyPants.injectInto(this) on your behalf.

Cheers,
 
 -Josh

2009/4/28 Borek <bor...@gmail.com>



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

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

Borek

unread,
Apr 28, 2009, 3:41:53 AM4/28/09
to Smartypants IOC
Thanks Josh, I didn't notice that you can call whenAskedFor even on
SmartyPants class (examples in the wiki use the injector object).

However, I'm still not sure about 2 things:

1) Where do you define the rules? Can it be done in the top level
application?
2) How exactly do you "build the instance". What SmartyPants method do
you call and from where?

Thanks,
Borek

On Apr 28, 12:53 am, Josh McDonald <j...@joshmcdonald.info> wrote:
> Hi Borek,
>
> Normally, you request to have fields injected using the [Inject] metadata,
> like so:
>
> public class Injectee
> {
>     [Inject]
>     public var service:ICustomerService;
>
> }
>
> And you specify your rules as part of your application bootstrap using the
> DSL:
>
> function buildRules():void
> {
>     // ...
>
> SmartyPants.whenAskedFor(ICustomerService).useSingletonOf(CustomerServiceImpl);
>     // ...
>
> }
>
> So now, when the injector builds an instance of Injectee, it will inject the
> correct service impl for you.
>
> If your dependant object is constructed via MXML instead of by the injector,
> you can use the <smartypants:RequestInjection/> tag, which will register an
> event listener for CREATION_COMPLETE and call
> SmartyPants.injectInto(this)on your behalf.
>
> Cheers,
>
>  -Josh
>
> 2009/4/28 Borek <bor...@gmail.com>
>
>
>
>
>
> > SmartyPants IOC looks good to me because it uses ActionScript to
> > define rules (I don't like XML configuration at all). However, I was
> > not able to find an example of what I would use DI primarily for:
> > injecting a service. Can someone post an example of an application
> > that would do something like the following:
>
> > * There is a Presenter that has a dependency on ICustomerService
> > * There is an implementation of CustomerService that can return an
> > ArrayCollection of Customer object. For the sake of simplicity, let's
> > ignore asynchronous nature of Flex network access.
> > * Presenter can store the value into a Model object
> > * View can then display the collection of Customers in a grid
>
> > I am most interested in the dependency injection on the Presenter/
> > Service layer. How do you inject that dependency? In what object will
> > the rule definitions live? Where do I get the instances from the IoC
> > container?
>
> > It would be much appreciated,
> > thanks,
> > Borek
>
> --
> "Therefore, send not to know For whom the bell tolls. It tolls for thee."
>
> Josh 'G-Funk' McDonald
>   -  j...@joshmcdonald.info

Josh McDonald

unread,
Apr 28, 2009, 3:51:07 AM4/28/09
to smartyp...@googlegroups.com
Hi Borek,

To answer your questions:

1) Soon we'll have a better way thanks to friendly prodding from Simen =], but for now you can define rules any time you like. In my smaller projects for clients I usually just call a static method from the creationComplete method of the root application. At work, there's a point in the application lifecycle of our framework where we build a bunch of rules.

2) Any instance that is created by the injector will have all dependencies injected into it. If you already have an instance (for example the Application instance, or anything instantiated via MXML), you can call SmartyPants.injectInto(myInstance) and it will then inject into any fields marked [Inject] on that object. You can also manually ask for instances from the injector using

SmartyPants.newRequest(injectee /* usually this */).forClass(SomeClass).named("optionalName").getInstance();

Due to the nature of Flex, you'll always have to bootstrap the injection of your application. I normally achieve this my using the <smartypants:RequestInjection/> MXML tag in my root Application.

-Josh

2009/4/28 Borek <bor...@gmail.com>
  -  jo...@joshmcdonald.info

Borek

unread,
Apr 28, 2009, 5:13:04 AM4/28/09
to Smartypants IOC
Sorry to be ignorant but I still don't quite understand how are
objects created / obtained from the container. So say that in MyView
(which is nested somewhere in the main application), I need to
instantiate MyPresenter. I want to do it in the initialize or
creationComplete event handler. Without an IoC container, I would do
something like:

function onCreateionComplete() : void {
this.presenter = new MyPresenter(this, new Dependency1(), new
Dependency2());
}

I want to avoid this because Dependency1 and Dependency2 may have
already been created for some other presenter or object up the logical
hierarchy. I have 2 options: either pass the dependencies manually
through the chain of nested Views, or use a Service Locator pattern.
The first option is cumbersome and I generally prefer DI over Service
Locator.

I would hope that SmartyPants will allow me to do something like this:

* in some global bootstrapping code, I would define Presenter's
dependencies using SmartyPants' rules
* here in the onCreationComplete() method, I would just call something
like SmartyPants.getInstanceOf(MyPresenter).

Can this be achieved with SmartyPants IoC? (Obviously, the problem is
how to pass on the view reference and I would probably need to do that
manually after the presenter reference has been obtained - something
like myPresenter.view = this.)

Thanks,
Borek

Josh McDonald

unread,
Apr 29, 2009, 12:18:28 AM4/29/09
to smartyp...@googlegroups.com
Hi Borek,

SmartyPants doesn't currently support constructor injection, so instead of passing dependencies to the constructor of MyPresenter, you would have to make them injected public fields. You can request an instance of MyPresenter by calling:

SmartyPants.newRequest(this).forClass(MyPresenter).getInstance();

Or you can simply make a public field:

[Inject]
public var presenter:MyPresenter;

and then in your creationComplete handler, after setting up the rules, just call

SmartyPants.injectInto(this);

-Josh

2009/4/28 Borek <bor...@gmail.com>
  -  jo...@joshmcdonald.info
Reply all
Reply to author
Forward
0 new messages