Basically, since the introduction of mapRule, everything should
already be in place API-wise - except for actually creating child
injection contexts. Thus, my proposal would be to add one method to
SwiftSuspender's injector:
Injector#createChildContext(usedWhenApplyingRule : InjectionConfig) : IInjector;
I hope that I'm not missing anything when I think that child contexts
should be used depending on the currently applied rule. If I do, this
obviously won't work as advertised.
Anyway, using this API, Josh's example as implemented with
SwiftSuspenders would look like this:
//the injectees would stay the same, of course
class ArmlessRobot
{
[Inject(name="left")]
var leftLeg:RobotLeg;
[Inject(name="right")]
var rightLeg:RobotLeg;
}
class RobotLeg
{
[Inject]
var foot:RobotFoot
}
class LeftFoot extends RobotFoot { ... }
class RightFoot extends RobotFoot { ... }
//here's where things change:
function configureInjector(injector : IInjector):void
{
// ...
var leftLegRule : InjectionConfig = injector.mapClass(RobotLeg,
RobotLeg, 'left');
var rightLegRule : InjectionConfig = injector.mapClass(RobotLeg,
RobotLeg, 'right');
var leftLegContext : IInjector = injector.createChildContext(leftLegRule);
leftLegContext.mapClass(RobotFoot, LeftFoot);
var rightLegContext : IInjector = injector.createChildContext(rightLegRule);
rightLegContext.mapClass(RobotFoot, RightFoot);
// ...
}
To me, this looks quite clean and straight forward.
There's one snag, though: the way the dependencies between Robotlegs
and SwiftSuspenders are set up (with Robotlegs depending on
SwiftSuspenders, but not the other way 'round), there's no way to
return types from SwiftSuspenders that Robotlegs knows about. I had
that same problem with Injector#mapRule and resolved it by typing
mapping rules as "*". This kinda worked for that usecase, but it won't
for creating child contexts.
I can only think of two different for solving this problem, of which I
tentatively favor the second one:
1: Integrate SwiftSuspenders into Robotlegs, making the point moot
2: Don't even try to encapsulate the feature. Instead, "just inject
it" into the startup command where the mappings are done, with "it"
being the SwiftSuspenders injector, typed as the concrete class which,
in distinction from IInjector, exposes the createChildContext method.
Another question would be that of when to implement/ integrate this
functionality. If we go the 2nd route, Robotlegs wouldn't be affected
at all, so maybe that's something I should mostly deal with on my own,
but even then I'd really appreciate feedback. My proposal for that'd
be getting SwiftSuspenders 1.0 out of the door quickly and then
pushing out a 1.1 with createChildContext after that. Depending on how
quickly I get through with that, we can then decide with which version
Robotlegs 1.0 should ship.
So, what do you all think about this?
cheers,
till
--
Till Schneidereit
Schneidereit Link GbR
technical concept, consulting, development
Tel: +49 40 970 7848 1
no worries, it's not like I absolutely need anything from you to get
this started. I thought about the issue some more and am now pretty
confident that my plan should work out. Thus, I think I'm going to
start implementing that tomorrow. With any luck, it won't take more
than a few hours.
There's one interesting point that affect RL, though, and that's about
how to integrate this functionality into RL. I'm more and more
thinking that we shouldn't integrate it at all and just let people
inject the SwiftSuspenders injector into their startup command with
the concrete type. With mapRule, things were pretty hairy already.
With createChildContext, there's just no clean interface to be had,
without marrying the project. And seeing as you where able to fully
resurrect the SP adapter, I think we should relegate such advanced
features to direct usage of the DI solution.