タイプとTypeLiterals経由のGuiceを使用して実行時にジェネリック型を再構築
-
12-09-2019 - |
質問
私はこのようなものですいくつかの種類があります。
// 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>
どのようにあなたがGuiceの中でそれを消費することができることなのFooを再作成するのでしょうか?私がこだわっているビットは、フーの第二パラメータ化された型のバーからKを相互参照する方法です。
ですから、例えば、
WildcardType kType = Types.subtypeOf(Object.class);
WildcardType barType =
Types.subtypeOf(Types.newParameterizedType(Bar.class, pipeKey));
ParameterizedType fooType =
Types.newParameterizedType(Foo.class, pipelineableType, pipeKey);
それは基本的だとして本当にこれは間違っているようです。
Foo<V extends Bar<? extends Object>, ? extends Object>
どのと同じものではありません。
Foo<V extends Bar<K>, K>
私はを後者の場合のようにKが整合型であること知っている。
任意のアイデア?
乾杯
マット
解決
バインダーのJavaDocからのます:
のGuiceは、現在バインドまたは注入することはできません このよう
Set<E>
などの一般的なタイプは、すべての 型パラメータは、完全でなければなりません 指定されています。
Foo
とK
がバインドされたときにあなたはV
のバインディングを作成することができます。
あなたは、キーの複数の種類のFoo
のバインディングを作成する必要がある場合は、それが簡単にこれらのバインディングを行うすることを可能にする方法を行うことができます。それを行う1つの方法は、モジュールで、このような方法を作成することです。
<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);
}
そして、あなたはこれらのクラスを持っている場合:
class StringValue implements Bar<String> {
...
}
class StringValueProcessor implements Foo<StringValue, String> {
...
}
あなたはこのようにバインディングを作成することができます:
bind(String.class, StringValue.class).to(StringValueProcessor.class);
... Guiceのは、このようなクラスに注入することができるようにます:
static class Target {
private final Foo<StringValue, String> foo;
@Inject
public Target(Foo<StringValue, String> foo) {
this.foo = foo;
}
}
他のヒント
のGuiceの工場はTypeVariable
のインスタンスを構築することはできません。あなたは、あなたがそれを必要として直接このインタフェースを実装する必要があります。
Guiceのは、完全修飾されていないタイプのバインディングを許可しないことに注意してください。たとえば、Map<String, Integer>
をバインドすることができますが、Map<K, V>
をバインドすることはできません。