On Thu, Nov 4, 2010 at 12:01 PM, Sam Berlin <[email protected]> wrote:
> On Thu, Nov 4, 2010 at 1:00 PM, Philippe Beaudoin
> <[email protected]> wrote:
>>
>> Just to come back on one of my questions: is injection automatically
>> performed on the fields and methods of instances bound with
>> toInstance()?
>
> Yup, injection is automatically performed on fields & methods for providers
> (provided they are bound as toProvider(..)).

And toInstance too? Neat!

>> Thanks for pointing out the MembersInjector. In this case I don't
>> think I can use it however, for two reasons. Tell me if I'm wrong:
>> 1) My SpyProvider is generic, so I would need to inject a
>> MembersInjector<T>. Would this work?
>
> Yup!  It's a pretty neat feature.  Another thing you can do is inject a
> TypeLiteral<T> if you have any need to inspect details of T at runtime.

Awesome! Injecting TypeLiteral<T> looks like a very powerful idea!

>> 2) I instantiate T using its @Inject constructor if present, so I need
>> to be able to instantiate T's dependencies that appear only in the
>> constructor parameter list. I don't think these dependencies can be
>> instantiated with the MembersInjector?
>
> MembersInjector will only replace the need to call injector.injectMembers
> (replacing it with membersInjector.injectMembers).  If you want to replace
> the injector.getInstance(..) calls for constructor dependencies, you would
> have to iterate through the dependencies in SpyProvider's constructor and
> could call binder().getProvider(dependency.getKey()) for each dependency,
> then call provider.get() for each and construct your instance with those.

If I do this in SpyProvider's constructor, wouldn't this force me to
make sure all dependencies of T's constructor are bound _before_ I
bind SpyProvider? I really like the fact that my current
implementation is independent of the binding order, as long as the
injector has access to all the dependencies when SpyProvider.get() is
called.

>  But!... you may want to look into toConstructor bindings, which may obviate
> the whole need for any of this.  An example:
>
> bind(Foo.class).annotatedWith(Internal.class).toConstructor(InjectionPoint.forConstructorOf(FooImpl.class).getMember());
>  bind(Foo.class).toProvider(new
> SpyProvider<Foo>(getProvider(Key.get(Foo.class, Internal.class)));
>  class SpyProvider<T> {
>        private final Provider<T> internalProvider;
>        SpyProvider(Provider<T> p) {
>          this.internalProvider = p;
>        }
>       T  get() {
>            return spy(internalProvider.get());
>        }
>    }

I have been trying many variations around your proposal (with an
@Internal annotation). In all cases I ran into the dreaded stack
overflow because SpyProvider<> was being injected into himself. As you
can see, my solution was to more or less rewrite Guice's injection
code to instantiate constructor dependencies myself.

Looking at the code you propose I have a number of questions:
1) Can you call getProvider(Key.get(Foo.class, Internal.class)) on the
binder even before the injector is created?
2) Why is toConstructor needed here? I would be happy with:
bind(Foo.class).annotatedWith(Internal.class).to(FooImpl.class);

Thanks a lot for your input Sam, it really help me get a better
understanding of Guice's little known features.

Cheers,

    Philippe

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to