pombreda / google-guice

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

A new and full-featured Injector introspection API (keys, implementations, dependencies, etc.) #29

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
To support tools, e.g. graph-drawing.  And what about the inverse,
Set<Binding> getDependents(Key) (in Container?)

Original issue reported on code.google.com by kevin...@gmail.com on 27 Feb 2007 at 3:12

GoogleCodeExporter commented 9 years ago
Both sound good to me. Should we also have getTrasitiveDependencies()?

Original comment by crazybob...@gmail.com on 27 Feb 2007 at 4:04

GoogleCodeExporter commented 9 years ago
changed summary from "Set<Key> Binding.getDependencies()"

Injector.getDependencyGraph() should return a nice DependencyGraph object 
supporting
the queries/traversals tools would need.  I think there may need to be two 
types of
edges, one for "depends on" and one for "is provided by"; these two are similar 
in
some ways but the depends-on relationship is significant for the life of the 
object.

Original comment by kevin...@gmail.com on 2 Mar 2007 at 6:06

GoogleCodeExporter commented 9 years ago

Original comment by kevin...@gmail.com on 13 Mar 2007 at 1:29

GoogleCodeExporter commented 9 years ago
Slight correction: in the *general* case the depends-on relationship is 
significant
for the life of the depending object, but we actually lack the information to 
know in
what cases the object might only be using the dependency for
construction/initialization and then forgetting about it.  It is *possible*, 
though
not necessarily likely, that we want to provide the ability for users to 
distinguish
between the two types of dependency, so that tools can reason properly about the
dependencies.

The dependency graph seems to have vertices of two types: Keys and 
Implementations. 
A Key is exactly what it is now in the API; an Implementation is the outcome of
performing injection resolution for a Key.  Internally we have several types of
Implementations:

  * those containing a single instance that was created and provided by the Module
using .toInstance()
  * those containing a Provider instance that was created and provided by the Module
using .toProvider(Provider)
  * those containing a Constructor which guice has found to be injectable

None of this has anything whatsoever to do with bindings or @ImplementedBy
annotations.  That information comes into play during injection resolution only 
and
then is no longer useful in this context.

more later, dinner's here.

Original comment by kevin...@gmail.com on 19 Mar 2007 at 4:16

GoogleCodeExporter commented 9 years ago
Continuing...

I missed a category.  I think I need to generalize the second bullet, so the 
complete
list of three would be

  * those referencing a single instance that was created and provided by the Module
using .toInstance()
  * those referencing another Implementation which serves as the provider for this
one (or you could even say the other Implementation can *provide* the provider 
for
this one; whooaaah)
  * those containing a Constructor which Guice has found to be injectable

The Implementation object also references a Scope.  For bullet point #1 there 
can't
be a Scope; it's effectively an automatic singleton as there is no other choice 
(we
don't clone).

It feels wrong now that our Binding object contains a getProvider() method. 
getProvider() does not seem to belong there; it is really this new 
Implementation
object I am talking about which represents Guice's knowledge of how to Provide
instances for a given Key.

Within an Injector, the "resolves-to" association between Key and 
Implementation is
many-to-one (1..* to 1).  Every Key can always be uniquely resolved into 
exactly one
Implementation, but every Implementation has one *or more* Keys which will 
resolve to it.

We've also discussed the "provides" association, which is from Implementation to
Implementation and is one-to-many (0..1 to 0..*).  An Implementation might not 
serve
as the provider for anyone, or it might serve as the provider for several other
Implementations (which conceivably differ only in scope?? puzzled here.); in the
reverse direction, an Implementation might have one unique other Implementation 
that
serves as its Provider, or none.

Now finally we have the long-awaited "depends on" association!  This is from
Implementation to Key and is many-to-many (0..* to 0..*).

Now all we need to do is define an interface exposing all this information, and 
then
include the necessary queries and traversals either as additional interface 
methods
or static utility methods.  Simple!

Original comment by kevin...@gmail.com on 19 Mar 2007 at 6:18

GoogleCodeExporter commented 9 years ago
Here is some crap.

public interface Implementation<T> {

  enum ProvisionStrategy {
    PRECONSTRUCTED_INSTANCE,
    INJECTABLE_CONSTRUCTOR,
    CUSTOM_PROVIDER,
  }

  ProvisionStrategy getProvisionStrategy();

  // Only the right method for the provision strategy will work; the others
  // will throw IllegalStateException.
  T getPreconstructedInstance();
  Constructor<? extends T> getInjectableConstructor();
  Implementation<? extends Provider<T>> getCustomProviderImplementation();

  Scope getScope();
  Set<Key<? super T>> getKeysThatResolveToThis();
  Set<Dependency<?>> getDependencies();
  Set<Dependency<?>> getDependents();
}

public interface Dependency<T> {
  Implementation<?> getDependent();
  Key<T> getKey();
  Implementation<? extends T> resolveKey();
  boolean isProviderDependency();
}

This is a straw man. pls dissect and discuss.

btw my intention is for issue 11 to be implemented atop this API.  I also think 
some
of the Binding stuff could perhaps be deprecated.

Original comment by kevin...@gmail.com on 19 Mar 2007 at 8:36

GoogleCodeExporter commented 9 years ago
Implementation could easily have getProvider() and getInstance() methods.  It is
precisely the "thing" that encompasses the information required to fulfill 
those. 
However, I think this may cause confusion; I'm trying to differentiate the API 
for
observing the static configuration of an Injector, from the API for using an 
Injector
to retrieve live application objects (the latter API should continue to be
Injector.java itself).

Original comment by kevin...@gmail.com on 19 Mar 2007 at 8:39

GoogleCodeExporter commented 9 years ago
too big for 1.1 :(

Original comment by kevin...@gmail.com on 29 Apr 2007 at 6:37

GoogleCodeExporter commented 9 years ago
I have iterated on the API design a little and have checked it in... I won't 
say the
revision number but I will just tell you that my newest design is only "half 
evil".  :)

Bob is insistent that this can be a simple extension of the existing "Binding" 
API. 
I have thought about this a lot and I still do not see how it can.  That API is
useful for working with bindings, but this is something very different.  This is
about keys and fully *resolved* keys (which the resolver may have had to follow
several bindings to get to, but where it ends up is not the same as a 
garden-variety
binding).

I'm optimistically re-tagging this for 1.1 because we may have an intern 
interested
in working on a graphical visualization tool.

Original comment by kevin...@gmail.com on 31 May 2007 at 9:23

GoogleCodeExporter commented 9 years ago

Original comment by limpbizkit on 30 May 2008 at 6:51

GoogleCodeExporter commented 9 years ago
Done. Elements provides full injector information.

Original comment by limpbizkit on 2 Aug 2008 at 11:04