xiaodududu / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Add utility method to get the Set<Dependency<?>> representing injection of an object #660

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
An object (as instance or provider) that exposes its dependencies explicitly 
may wish to depend on the injection of other specific objects as well as 
availability of targets of given keys.  There should be a method (in either the 
Dependency class itself or a utility extension) tentatively named 
"dependenciesOfObject" to get the set of dependencies corresponding to the 
injection of an object.

dependenciesOfObject(obj) would be equivalent to 
Dependency.forInjectionPoints(InjectionPoint.forInstanceMethodsAndFields(obj.get
Class())), the same chain of calls that occurs in BindingBuilder#toInstance and 
InstanceBindingImpl#getDependencies.

USE CASE:
A Google-internal class uses Guice for a number of purposes but in one case 
takes a list of widgets (redacted term) as a constructor parameter.  (Probably 
the better design is to get the list via Multibinder, but that migration will 
affect a lot of code, so it won't happen right away.)  For maximum flexibility, 
the constructor allows widgets to be specified in the form of keys, providers, 
or instances.

The class had been instantiating the widgets lazily, which allowed certain 
problems to go undetected.  When I tried to change it to instantiate the 
widgets during injector creation, I ran into dependency problems manifest via 
the exception, "This Provider cannot be used until the Injector has been 
created."  My current idea is to build the widget list via a Multibinder in a 
private child binder, which has the side effect of establishing the correct 
dependencies.  However, this would mean binding the list for use by a single 
injection point in the same file, which is silly; I prefer more direct 
techniques in such cases.  I looked into using HasDependencies directly, and 
the proposed new method would make such usage more convenient.  (I am actually 
planning to stay with the Multibinder/private child binder solution in 
anticipation of the migration described above.)

Original issue reported on code.google.com by mattmccu...@google.com on 11 Oct 2011 at 5:36

GoogleCodeExporter commented 9 years ago
Is there a reason 
Dependency.forInjectionPoints(InjectionPoint.forInstanceMethodsAndFields(obj.get
Class())) itself can't do the trick?

Original comment by sberlin on 11 Oct 2011 at 12:44

GoogleCodeExporter commented 9 years ago
No, but neither is there a reason that writing one's own dependency injection 
framework can't do the trick, and yet you provide Guice.  Libraries are 
supposed to make things easy for their callers.

It took me some time to convince myself that that chain of calls was the proper 
way to establish dependencies on an object being injected and there wasn't 
another better way that I was missing.  Guice should provide a single method so 
programmers don't duplicate that mental work.

Original comment by mattmccu...@google.com on 11 Oct 2011 at 3:32

GoogleCodeExporter commented 9 years ago
I think we can agree that writing a DI framework like Guice is a little more 
complex than chaining two method calls together.  Guice isn't attempting to 
provide utility methods for every possible usecase, it's just providing the 
means for users to get what they need and expose the common scenarios.  A small 
API makes it easier for people to understand.

If it turns out that writing 
Dependency.forInjectionPoints(InjectionPoint.forInstanceMethodsAndFields(..)) 
is an incredibly common use case, it's easy to make an API.

Original comment by sberlin on 16 Oct 2011 at 3:50