Реконструкция универсальных типов во время выполнения с помощью Guice через Types и TypeLiterals - PullRequest
3 голосов
/ 11 июля 2009

У меня есть несколько типов, подобных этому

// 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>

Как можно воссоздать Foo так, чтобы вы могли употреблять его в Guice? Бит, на котором я застрял, заключается в том, как связать K из Bar со вторым параметризованным типом Foo.

Так, например,

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 - согласованный тип.

Есть идеи?

Приветствия

Мэтт

Ответы [ 2 ]

4 голосов
/ 13 июля 2009

Из JavaDoc для Binder :

Guice в настоящее время не может связывать или вводить универсальный тип, такой как Set<E> все параметры типа должны быть полностью указано.

Вы можете создавать привязки для Foo, когда K и V связаны. Если вам нужно сделать привязки для Foo для ключей более одного типа, вы можете создать метод, который облегчит выполнение этих привязок. Один из способов сделать это - создать такой метод в вашем модуле:

<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;
  }
}
0 голосов
/ 13 июля 2009

Фабрика Guice не может построить TypeVariable экземпляров. Вам нужно будет реализовать этот интерфейс напрямую по мере необходимости.

Обратите внимание, что Guice не разрешает привязки для типов, которые не полностью квалифицированы. Например, вы можете связать Map<String, Integer>, но не можете связать Map<K, V>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...