在运行时使用 Guice 通过类型和 TypeLiterals 重建泛型类型

发布于 2024-07-26 22:30:41 字数 827 浏览 4 评论 0原文

我有一些像这样的类型

// 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 中使用它? 我遇到的问题是如何将 Bar 中的 K 交叉引用到 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 是一致类型。

有任何想法吗?

干杯

马特

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空城旧梦 2024-08-02 22:30:41

来自 Binder

Guice 目前无法绑定或注入
泛型类型,例如 Set all
类型参数必须是完整的
指定。

当绑定 KV 时,您可以为 Foo 创建绑定。
如果您需要为多种类型的键为 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;
  }
}

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;
  }
}
各自安好 2024-08-02 22:30:41

Guice 的工厂无法构建 TypeVariable 实例。 您需要根据需要直接实现该接口。

请注意,Guice 不允许绑定非完全限定的类型。 例如,您可以绑定 Map,但不能绑定 Map

Guice's factory cannot build TypeVariable instances. You'll need to implement this interface directly as you need it.

Note that Guice doesn't allow bindings for types that aren't fully-qualified. For example, you can bind a Map<String, Integer> but you can't bind a Map<K, V>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文