2

我想提供通用实例而不在模块实现中明确说明通用参数。

假设我有一个非常优化的 Map 实现,并希望每个人都使用它。

class MyVeryOptimizedHashMap<K, V> implements Map<K, V> {}

我知道,以下用法不是最好的设计模式,但就示例而言,这是一个有效的要求:

class SomeInjectee {
  @Inject
  private Map<String, Integer> myMap;
}

要将此实例绑定到我选择的提供程序,请执行以下模块声明:

class GenericMapModule extends AbstractModule {
  protected void configure() {
    bind(new TypeLiteral<Map<String, Integer>>() {}).toProvider(new TypeLiteral<Provider<MyVeryOptimizedHashMap<String, Integer>>>() {});
  }
}

问题是我必须明确声明泛型类型参数,我不可能对所有可能的类型都这样做:

class SomeOtherInjectee{
  @Inject
  private Map<SomeUnknownKey, Long> myMap;
}

这解决了我的问题,但不是很优雅:

class GenericModule extends AbstractModule {
  protected void configure() {
    bind(new TypeLiteral<Map<?, ?>>() {}).toProvider(new Provider<Map<?,?>>() {
      public Map<?, ?> get() {
        return new MyVeryOptimizedHashMap();
      }
    });
  }
}

class SomeOtherInjectee {
  private Map<SomeUnknownKey, Long> myMap;

  @Inject
  void setMap(Map<?, ?> mapInstance) {
    myMap = (Map<SomeUnknownKey, Long>) mapInstance;
  }
}

我正在寻找的是这样的:

class GenericModule extends AbstractModule {
  protected void configure() {
    bind(TypeLiteral.anyGenericVariant(Map.class)).toProvider(new TypeLiteral<Provider<MyVeryOptimizedHashMap>>(){});        
  }
}
4

1 回答 1

0

如果适用于您的情况,我会尝试使用静态实用程序方法。

class SomeOtherInjectee {
    private Map<SomeUnknownKey, Long> myMap = newOptimizedMap();

如果这不适用,那么正如您所见,Guice 在泛型方面非常精确,即每个泛型变体代表一个唯一的绑定。因此,anyGenericVariant 实际上必须列出所有可能的变体并提前进行绑定。疯狂的。

在这种情况下,您可以做的是使用 TypeListener 注册自定义注入。它看起来像

class SomeOtherInjectee {
    @InjectOptimizedMap private Map<SomeUnknownKey, Long> myMap;

或您制作的任何自定义注入注释。

有关如何进行自定义注入的完整示例和说明,请参见此处。

于 2013-04-18T07:51:28.187 回答