mapSingleton vs. mapValue
using mapSingleton I have a working example of proxy injection. in my AppContext:
injector.mapSingleton(UserProxy);
then, in my StartUpCommand:
public class StartUpCommand extends Command
{
[Inject] public var userProxy:UserProxy;
override public function execute ():void
{
trace('StartUpCommand', userProxy);
}
}
all working fine, great. however, looking at this:
http://knowledge.robotlegs.org/faqs/framework-core/injection-mappin...
i understand that i can change my AppContext code to this to achieve the same result:
var userProxy:UserProxy = new UserProxy();
injector.mapValue(StartUpCommand, userProxy);
however if I do that i get the following error:
Error: Injector is missing a rule to handle injection into target [object StartUpCommand]. Target dependency: com.client.appname.model::UserProxy
woe is me! what gives?
Comments are currently closed for this discussion. You can start a new one.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
Support Staff 1 Posted by Joel Hooks on 14 Dec, 2009 05:02 PM
On Dec 14, 2009, at 10:59 AM, Richard Willis wrote:
> var userProxy:UserProxy = new UserProxy();
> injector.mapValue(StartUpCommand, userProxy);
>
> however if I do that i get the following error:
>
> Error: Injector is missing a rule to handle injection into target [object StartUpCommand]. Target dependency: com.client.appname.model::UserProxy
var userProxy:UserProxy = new UserProxy();
injector.mapValue(UserProxy, userProxy);
You are mapping the value of a UserProxy class with a specific instance, not mapping the value to BE injected in a specific class.
Support Staff 2 Posted by Shaun Smith on 14 Dec, 2009 07:52 PM
Indeed, the way you were doing it initially seems more appropriate, ie:
Unless you have a reason to eagerly instantiate the proxy, in which case:
However, it's usually better to let the framework instantiate the class lazily (as it does with mapSingleton), rather than eagerly (as with mapValue).
3 Posted by Richard Willis on 15 Dec, 2009 01:37 PM
thanks guys.
why would you consider mapSingleton's lazy instans. to be better shaun? i realise it doesn't actually create a singleton, but anything with that word in it tends to make me a bit nervous.plus my understanding is that mapSingleton just injects its given class willy-nilly around the architecture blindly. isn't that a bit of an unnecessary overhead?
i'm new to dep. inj. (just started this week) so if sorry if these come across as idiotic newbie questions. just tryin to learn.
:)
Support Staff 4 Posted by Till Schneidere... on 15 Dec, 2009 02:00 PM
Hey Richard,
> why would you consider mapSingleton's lazy instans. to be better shaun? i realise it doesn't actually create a singleton, but anything with that word in it tends to make me a bit nervous.
In my opinion, mapSingleton has three advantages over mapValue:
- The fact that it lazily creates its instance means that the instance
is created exactly if and when it is needed, possibly reducing
initialization overhead in cases where it is used for seldomly
accessed functionality
- It clearly communicates the intent: The developer wants exactly one
shared instance of this class to be used for every request made
- It simply reduces what you have to type and automates priming the
singleton itself with dependencies by instantiating it internally and
immediately injecting into it
As Shaun said some time ago, Singletons with a big "S" are the
original anti-pattern and should be avoided at all costs. On the other
hand, there's nothing wrong with explicitly stating that you want each
request for a certain type (and possibly a certain name) to be
fulfilled with the same instance of a class. And that's exactly what
singletons with a small "s" are for.
> plus my understanding is that mapSingleton just injects its given class willy-nilly around the architecture blindly. isn't that a bit of an unnecessary overhead?
I'm not sure what you mean by that, maybe you can elaborate a bit?
After the instance has been created at first request, value and
singleton mappings should be pretty much identical in behavior and
overhead.
> i'm new to dep. inj. (just started this week) so if sorry if these come across as idiotic newbie questions. just tryin to learn.
No worries. Feel free to check the knowledge database and ask questions.
cheers,
till
5 Posted by Tyler Wright on 15 Dec, 2009 07:22 PM
It's usually better to say why it's better, rather than just saying that it is. :)
The only functional difference I see, as Till pointed out, is that mapSingleton won't create the instance until it's needed, possibly reducing initialization time and saving some runtime memory. From project's I've worked on this seems rare and the savings would be unnoticeable.
Personally I like mapValue best (at least today I do), considering that the Injector's singleton is really only single to itself (not system-wide) and so not really a Singleton, which is why we feel better using it.
Good discussion, thanks!
6 Posted by Tim Oxley on 16 Dec, 2009 03:44 AM
Perhaps the problem is the big S. mapSingleton should be renamed mapsingleton ;)
Support Staff 7 Posted by Shaun Smith on 16 Dec, 2009 05:48 PM
@Tim: Haha! Believe it or not, I had actually considered that!
@Tyler:
One of the benefits of DI is that client code doesn't have to know "how" to construct the objects/collaborators/dependencies that it needs to get it's job done. The task of constructing such an object can be left to the container.
The benefits of Lazy vs Eager aside, using mapValue requires that you construct said object yourself. If the constructor of the object changes you will need to change the code that constructs it. The container, on the other hand, would most likely be able to figure out how to construct the new object without any changes to your code.
Also, manually constructing objects that rely on setter injection is error prone: you might forget to set the appropriate dependencies after construction. Leaving construction to the container will safe guard against that.
The only time that I use mapValue is when I need to put an object into the container that already exists. For everything else, I leave it up to the container to build my objects for me.
Finally (and very subjectively), using mapValue makes me feel like I'm using the Service Locator / Registry pattern - granted, an IoC container IS a registry of sorts - I just don't like it!
8 Posted by Tyler Wright on 17 Dec, 2009 03:33 AM
I see your point. DI isn't my primary workflow for object creation - I
assumed that each object to map wouldn't often be injected itself, otherwise
you have to start worrying about the order of your mappings. But I can see
that I would want a Controller injected into, and then to be provided via
injection into other objects.
So mapSingleton does the following, except lazily: mapValue(Type,
instantiate(MyType));
re: registry - everything needs a home, a registry can be a beautiful
organization of data and configuration, making a system easy to update and
extend (as we see from RL Injector/Context). It's only ugly when it becomes
a global trough for all the table scraps. :)
Till Schneidereit closed this discussion on 02 Mar, 2010 12:55 PM.