Added Binding.getProviderBinding()
git-svn-id: https://google-guice.googlecode.com/svn/trunk@361 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/Binding.java b/src/com/google/inject/Binding.java
index 5dcd6f3..d4a21d8 100644
--- a/src/com/google/inject/Binding.java
+++ b/src/com/google/inject/Binding.java
@@ -17,6 +17,7 @@
package com.google.inject;
import com.google.inject.spi.BindingVisitor;
+import com.google.inject.spi.ProviderBinding;
/**
* A mapping from a key (type and optional annotation) to a provider of
@@ -50,6 +51,11 @@
Provider<T> getProvider();
/**
+ * Gets the synthetic binding to this binding's Provider.
+ */
+ ProviderBinding<T> getProviderBinding();
+
+ /**
* Returns the scope applied by this binding.
*/
Scope getScope();
diff --git a/src/com/google/inject/BindingImpl.java b/src/com/google/inject/BindingImpl.java
index 9b3d729..acf4ae3 100644
--- a/src/com/google/inject/BindingImpl.java
+++ b/src/com/google/inject/BindingImpl.java
@@ -17,6 +17,7 @@
package com.google.inject;
import com.google.inject.internal.ToStringBuilder;
+import com.google.inject.spi.ProviderBinding;
/**
* @author crazybob@google.com (Bob Lee)
@@ -55,6 +56,13 @@
return provider;
}
+ @SuppressWarnings("unchecked")
+ public ProviderBinding<T> getProviderBinding() {
+ // ProviderBinding is the only type of binding that can be generated for
+ // a Provider<T>.
+ return (ProviderBinding<T>) injector.getBinding(key.providerKey());
+ }
+
InternalFactory<? extends T> getInternalFactory() {
return internalFactory;
}
diff --git a/src/com/google/inject/Injector.java b/src/com/google/inject/Injector.java
index 771d1e8..ede77eb 100644
--- a/src/com/google/inject/Injector.java
+++ b/src/com/google/inject/Injector.java
@@ -76,6 +76,16 @@
<T> Binding<T> getBinding(Key<T> key);
/**
+ * Gets a binding for the given type, or null if no binding for this type is
+ * found. Returns explicit bindings as well as those synthesized by the
+ * container such as bindings for converted constants, etc.
+ *
+ * <p>This method is part of the Injector Introspection API and is
+ * primarily intended for use by tools.
+ */
+ <T> Binding<T> getBinding(Class<T> type);
+
+ /**
* Finds all bindings to the given type. This method is part of the Injector
* Introspection API and is primarily intended for use by tools.
*/
diff --git a/src/com/google/inject/InjectorImpl.java b/src/com/google/inject/InjectorImpl.java
index 2f694bd..0e9cda8 100644
--- a/src/com/google/inject/InjectorImpl.java
+++ b/src/com/google/inject/InjectorImpl.java
@@ -161,6 +161,10 @@
return getJitBindingImpl(key);
}
+ public <T> Binding<T> getBinding(Class<T> type) {
+ return getBinding(Key.get(type));
+ }
+
/**
* Gets a binding which was specified explicitly in a module.
*/
@@ -535,7 +539,9 @@
@SuppressWarnings("unchecked")
public T get(InternalContext context) {
- // We know this cast is safe (assuming getConstructor() is safe).
+ // This may not actually be safe because it could return a super type
+ // of T (if that's all the client needs), but it should be OK in
+ // practice thanks to the wonders of erasure.
return (T) constructorInjector.construct(
context, context.getExpectedType());
}
diff --git a/src/com/google/inject/Key.java b/src/com/google/inject/Key.java
index c5b4621..aba867f 100644
--- a/src/com/google/inject/Key.java
+++ b/src/com/google/inject/Key.java
@@ -175,6 +175,13 @@
return typeLiteral.getRawType();
}
+ /**
+ * Gets the key of this key's provider.
+ */
+ Key<Provider<T>> providerKey() {
+ return ofType(typeLiteral.providerType());
+ }
+
public boolean equals(Object o) {
if (o == this) {
return true;
@@ -306,6 +313,14 @@
}
/**
+ * Returns a new key of the specified type with the same annotation as this
+ * key.
+ */
+ <T> Key<T> ofType(TypeLiteral<T> type) {
+ return new SimpleKey<T>(type, annotationStrategy);
+ }
+
+ /**
* Returns true if this key has annotation attributes.
* @return
*/
diff --git a/src/com/google/inject/TypeLiteral.java b/src/com/google/inject/TypeLiteral.java
index 6044350..a945a57 100644
--- a/src/com/google/inject/TypeLiteral.java
+++ b/src/com/google/inject/TypeLiteral.java
@@ -131,6 +131,30 @@
return type;
}
+ /**
+ * Gets the type of this type's provider.
+ */
+ @SuppressWarnings("unchecked")
+ TypeLiteral<Provider<T>> providerType() {
+ final Type[] typeParameters = new Type[] { getType() };
+
+ // This cast is safe and wouldn't generate a warning if Type had a type
+ // parameter.
+ return (TypeLiteral<Provider<T>>) get(new ParameterizedType() {
+ public Type[] getActualTypeArguments() {
+ return typeParameters;
+ }
+
+ public Type getRawType() {
+ return Provider.class;
+ }
+
+ public Type getOwnerType() {
+ return null;
+ }
+ });
+ }
+
public int hashCode() {
return this.hashCode;
}
diff --git a/test/com/google/inject/BindingTest.java b/test/com/google/inject/BindingTest.java
index 545c6ed..f4ec2b7 100644
--- a/test/com/google/inject/BindingTest.java
+++ b/test/com/google/inject/BindingTest.java
@@ -33,6 +33,20 @@
*/
public class BindingTest extends TestCase {
+ public void testProviderBinding() {
+ Injector injector = Guice.createInjector();
+ Binding<Bob> bobBinding = injector.getBinding(Bob.class);
+ assertTrue(bobBinding.getProvider().get() instanceof Bob);
+ Binding<Provider<Bob>> bobProviderBinding = bobBinding.getProviderBinding();
+ assertTrue(bobProviderBinding.getProvider().get().get() instanceof Bob);
+ Binding<Provider<Provider<Bob>>> bobProviderProviderBinding
+ = bobProviderBinding.getProviderBinding();
+ assertTrue(bobProviderProviderBinding.getProvider().get().get().get()
+ instanceof Bob);
+ }
+
+ static class Bob {}
+
public void testVisitor() {
MyVisitor myVisitor = new MyVisitor();