Reconstructing generic types at runtime with Guice via Types and TypeLiterals
generics, guice, reflection, runtime
Solution
From the JavaDoc for Binder:
Guice cannot currently bind or inject a generic type, such as `Set<E>` all type parameters must be fully specified.
You can create bindings for `Foo` when `K` and `V` are bound. If you need to make bindings for `Foo` for more than one type of key, you can make a method that makes it easier to do these bindings. One way to do that is to create a method like this in your module:
<K, V extends Bar<K>> AnnotatedBindingBuilder<Foo<V, K>> bind(Class<K> keyType,
Class<V> barType) {
ParameterizedType bType = Types.newParameterizedType(Bar.class, keyType);
ParameterizedType fType = Types.newParameterizedType(Foo.class, barType,
keyType);
@SuppressWarnings("unchecked")
TypeLiteral<Foo<V, K>> typeLiteral =
(TypeLiteral<Foo<V, K>>) TypeLiteral.get(fType);
return bind(typeLiteral);
}
Then if you have these classes:
class StringValue implements Bar<String> {
...
}
class StringValueProcessor implements Foo<StringValue, String> {
...
}
You can create a binding like this:
bind(String.class, StringValue.class).to(StringValueProcessor.class);
...so that Guice could inject into a class like this:
static class Target {
private final Foo<StringValue, String> foo;
@Inject
public Target(Foo<StringValue, String> foo) {
this.foo = foo;
}
}
Problem
I have a few types that are like this ``` // a value that is aware of its key type (K) Bar<K> // something that deals with such values and keys Foo<V extends Bar<K>, K> ``` How would one recreate Foo such that you could consume it in Guice? The bit I'm stuck on is how to cross reference the K from Bar to the 2nd parameterized type of Foo. So for example, ``` WildcardType kType = Types.subtypeOf(Object.class); WildcardType barType = Types.subtypeOf(Types.newParameterizedType(Bar.class, pipeKey)); ParameterizedType fooType = Types.newParameterizedType(Foo.class, pipelineableType, pipeKey); ``` Really this seems wrong as it's basically: ``` Foo<V extends Bar<? extends Object>, ? extends Object> ``` Which is not the same thing as: ``` Foo<V extends Bar<K>, K> ``` As in the latter case I know that K is a consistent type. Any ideas? Cheers Matt