useSingletonOf and Partial Injection

4 views
Skip to first unread message

dtyrell

unread,
Apr 17, 2009, 6:56:00 AM4/17/09
to Smartypants IOC
Hi Josh, 2 quickies:

1. useSingletonOf: I assume this means a scoped Singleton? ie. Only
for that Injector. Is this correct? (Or will it be shared between
injectors?)

2. Partial Injection (for lack of a better term) seems impossible at
present. Lets say that I have one main injector for my application/
module context, and I create a temporary injector for a more locally
scoped context, I am unable to inject into an object that requires
both - an error will be thrown if the first injector doesn't have a
rule for dependencies that I plan to inject with the second. Is there
an option to suppress that error and continue with the injections?

Many thanks,
Shaun

Josh McDonald

unread,
Apr 17, 2009, 10:41:10 PM4/17/09
to smartyp...@googlegroups.com
Yeah, all rules are injector-specific. If your class is annotated [Singleton] and you don't specifically create a rule saying otherwise, it'll be one singleton per injector.

Not sure exactly what you're trying to achieve with partial injection, but you can probably fake it for now using a live injection. the injector will attempt to create for a live injection, but if it can't (for example it's looking for an interface rather than a class), it will continue silently, and like other live injections it'll be populated whenever the injector gets a new matching rule, or in the case of a live rule, whenever the value changes.

As for more locally scoped contexts, that's related to the robot legs problem, and I'm thinking of adding scopes to the rules rather than setting up sub-injectors, which is what Guice does. Adding scopes would probably mean a sizeable change, but could hve other benefits, and as rules would be grouped in hierarchical scopes we could do some verification of the rulesets to aid debugging when things don't quite go how you want them to. I'd love to hear your thoughts on the matter though, as it sounds like you've been giving it some thought as well.

-Josh

2009/4/17 dtyrell <Dar...@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/

darscan

unread,
Apr 18, 2009, 8:51:26 PM4/18/09
to Smartypants IOC
Hmm, maybe partial injection is a silly term. How about an option to
ignore missing rules when injecting? Something like strict=false
perhaps.

To put this in context: I have a framework that creates and executes
Commands in response to Events. The factory responsible for this has a
framework-wide injector (shared by all framework actors). After
constructing a Command the factory uses that injector to pump
application-wide values into the Command before calling execute().
But, the Command Class might have declared a dependency on the
concrete Event responsible for it's creation. I could (and currently
do) set up a "temporary" rule on the injector like this:

var eventClass:Class = Class( getDefinitionByName
( getQualifiedClassName( event ) ) );
injector.newRule().whenAskedFor( eventClass ).useValue( event );
injector.injectInto( command );
injector.newRule().whenAskedFor( eventClass ).defaultBehaviour();
command.execute();

I'm not entirely happy with this approach though. This is just one
example, but there are other places where the "temporary" rule might
override previously configured rules. I would prefer to create a
temporary injector just for that Event. Something like:

injector.injectInto( command );
var eventInjector:Injector = SmartyPants.getOrCreateInjectorFor
( this );
eventInjector.newRule().whenAskedFor( eventClass ).useValue( event );
eventInjector.injectInto( command );
eventInjector.newRule().whenAskedFor( eventClass ).defaultBehaviour();
command.execute();

But, this throws an error as the eventInjector doesn't have rules for
any of the Command's other dependencies, and the framework-wide
injector doesn't have a rule for the concrete Event. The strict option
might look like this:

injectInto( targetInstance: Object, strict: Boolean = true );

When set to false, no errors are thrown if a rule doesn't exist for a
dependency.

I'm not too clued up on Guice (I have no Java experience), but perhaps
I am trying to enable what you called sub-injectors.

Many thanks,
Shaun

On Apr 18, 4:41 am, Josh McDonald <j...@joshmcdonald.info> wrote:
> Yeah, all rules are injector-specific. If your class is annotated
> [Singleton] and you don't specifically create a rule saying otherwise, it'll
> be one singleton per injector.
>
> Not sure exactly what you're trying to achieve with partial injection, but
> you can probably fake it for now using a live injection. the injector will
> attempt to create for a live injection, but if it can't (for example it's
> looking for an interface rather than a class), it will continue silently,
> and like other live injections it'll be populated whenever the injector gets
> a new matching rule, or in the case of a live rule, whenever the value
> changes.
>
> As for more locally scoped contexts, that's related to the robot legs
> problem, and I'm thinking of adding scopes to the rules rather than setting
> up sub-injectors, which is what Guice does. Adding scopes would probably
> mean a sizeable change, but could hve other benefits, and as rules would be
> grouped in hierarchical scopes we could do some verification of the rulesets
> to aid debugging when things don't quite go how you want them to. I'd love
> to hear your thoughts on the matter though, as it sounds like you've been
> giving it some thought as well.
>
> -Josh
>
> 2009/4/17 dtyrell <Dars...@gmail.com>
>
>
>
>
>
> > Hi Josh, 2 quickies:
>
> > 1. useSingletonOf: I assume this means a scoped Singleton? ie. Only
> > for that Injector. Is this correct? (Or will it be shared between
> > injectors?)
>
> > 2. Partial Injection (for lack of a better term) seems impossible at
> > present. Lets say that I have one main injector for my application/
> > module context, and I create a temporary injector for a more locally
> > scoped context, I am unable to inject into an object that requires
> > both - an error will be thrown if the first injector doesn't have a
> > rule for dependencies that I plan to inject with the second. Is there
> > an option to suppress that error and continue with the injections?
>
> > Many thanks,
> > Shaun
>
> --
> "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 19, 2009, 6:31:57 AM4/19/09
to smartyp...@googlegroups.com
Live injection points already behave in that way, but I think what you're after is definitely something akin to sub-injectors. There's probably a better way we can deal with your specific needs though. There's no need to set everything via the injector. Instead of mapping things like eventClass and so on, you could just do this:

if ("event" in command)
{
  command["event"] = incomingEvent;
}
command.execute();

Or you could even just use your own metadata, say:

[EventField]
public var triggetEvent:MyEventType;

and leverage SmartyPants' reflection classes to write a small util for your framework that will inspect the command class and let you know the name of the field in which to pass the trigger event. That way you don't need to include the trigger event in your Command interface, just execute():void, and that will allow you to start certain commands in future without a triggering event, which you'll eventually want to do I'm sure.

I find that in most cases, if you're trying to do something really complex with the injector there's probably a better way to approach the issue at hand that will turn out to be a more elegant solution in the end.

-Josh


2009/4/19 darscan <Dar...@gmail.com>
  -  jo...@joshmcdonald.info

darscan

unread,
Apr 19, 2009, 10:51:33 AM4/19/09
to Smartypants IOC
Agreed, I definitely need to figure out a more elegant solution to
this. By the way, the trigger event is not included in the Command
interface, the interface defines only a single method (execute), and
the event is declared as a dependency only if the Command actually
needs to make use of it. For example:

public class SomeCommand implements ICommand
{
[Inject]
public var event:SomeSpecificEvent;

[Inject]
public var someService:ISomeService;

public function execute():void
{
// Inspect the event here
}
}

Initially, my command interface defined execute to take an Event
parameter, but this meant you'd have to cast the event in order to use
it. PureMVC requires a LOT of casting, and the goal of my framework
was to remove it all.

My concern with using custom annotations is that users of my little
framework would then have to remember to declare command event
dependencies differently to everything else. Perhaps that's cool
though. I'll give it some more thought.

I'm pretty sure that I'm using SmartyPants in some unusual/bizarre
ways, so I appreciate you taking the time to respond to my ramblings.

Cheers!
Shaun

On Apr 19, 12:31 pm, Josh McDonald <j...@joshmcdonald.info> wrote:
> Live injection points already behave in that way, but I think what you're
> after is definitely something akin to sub-injectors. There's probably a
> better way we can deal with your specific needs though. There's no need to
> set everything via the injector. Instead of mapping things like eventClass
> and so on, you could just do this:
>
> if ("event" in command)
> {
>   command["event"] = incomingEvent;}
>
> command.execute();
>
> Or you could even just use your own metadata, say:
>
> [EventField]
> public var triggetEvent:MyEventType;
>
> and leverage SmartyPants' reflection classes to write a small util for your
> framework that will inspect the command class and let you know the name of
> the field in which to pass the trigger event. That way you don't need to
> include the trigger event in your Command interface, just execute():void,
> and that will allow you to start certain commands in future without a
> triggering event, which you'll eventually want to do I'm sure.
>
> I find that in most cases, if you're trying to do something really complex
> with the injector there's probably a better way to approach the issue at
> hand that will turn out to be a more elegant solution in the end.
>
> -Josh
>
> 2009/4/19 darscan <Dars...@gmail.com>
Reply all
Reply to author
Forward
0 new messages