Guice SPI: find bindings by wildcard types

2020-07-20 04:45发布

问题:

Guice provides a means to find all bindings for a given type (Injector#findBindingsByType) and it also provides a TypeLiteral class from which it seems possible to construct a wildcard type. What I would like to do is find all bindings for some type that is parameterised by a wildcard type but I can't figure out how to do it. A look at the guice src suggests I might be barking up the wrong tree but I figured I'd ask around anyway... so for example given a type

Foo<E extends Bar>
BarImplOne implements Bar
BarImplTwo implements Bar

and some bindings like

bind(new TypeLiteral<Foo<BarImplOne>>() {}).to(MyFooOne.class);
bind(new TypeLiteral<Foo<BarImplTwo>>() {}).to(MyFooTwo.class);

then I want to be able to discover both bindings with something like

Injector.findBindingsByType(TypeLiteral.get(Types.newParameterizedType(Foo.class, Types.subtypeOf(Bar.class))));

Any ideas?

Cheers Matt

回答1:

Unfortunately, there's no out-of-the-box API that will tell you whether one TypeLiteral is assignable from another. You'll need to do an old-school loop with a bunch of hideous instanceof checks. Something gross like this:

for (Map.Entry<Key<?>, Binding<?>> entry 
    : injector.getBindings().entrySet()) {
  Type type = entry.getKey().getTypeLiteral().getType();
  if (!(type instanceof ParameterizedType)) continue;

  ParameterizedType parameterized = (ParameterizedType) type;
  if (parameterizedType.getRawType() != Foo.class) continue;

  Type parameter = .getActualTypeArguments()[0]
  if (!(parameter instanceof Class)) continue;

  Class<?> parameterClass = (Class<?>) parameter;
  if (!Bar.class.isAssignableFrom(parameterClass)) continue;

  results.add(entry);
}

Of course, it would be much nicer to do something using an off-the-shelf API. I'd welcome an contribution to Guice that implements and tests TypeLiteral.isAssignableFrom(TypeLiteral). Contact our user's list to volunteer!