Olivier Grégoire
Olivier Grégoire

Reputation: 35477

Bind instances dynamically in Guice

Note: despite the similar name, the answer of Dynamically bind instances using guice can't solve my problem since I need all the injections directly injected and not in a map.

I have a set of pairs of Class -> instances. They are stored in a Guava's ClassToInstanceMap. I want to pass that ClassToInstanceMap to my custom Module and go through each entry to perform the actual binding. How do I do that?

import com.google.common.collect.ImmutableClassToInstanceMap;
import com.google.inject.AbstractModule;
import com.google.inject.Module;

public class InstanceModuleBuilder {
  private final ImmutableClassToInstanceMap.Builder<Object> instancesBuilder = ImmutableClassToInstanceMap.builder();
  public <T> InstanceModuleBuilder bind(Class<T> type, T instance) {
    instancesBuilder.put(type, instance);
    return this;
  }
  public Module build() {
    return new InstanceModule(instancesBuilder.build());
  }
  static class InstanceModule extends AbstractModule {
    private final ImmutableClassToInstanceMap<Object> instances;
    InstanceModule(ImmutableClassToInstanceMap<Object> instances) {
      this.instances = instances;
    }
    @Override protected void configure() {
      for (Class<?> type : instances.keySet()) {
        bind(type).toInstance(instances.getInstance(type)); // Line with error
      }
    }
  }
}

When I compile the above code, I get the following error:

InstanceModuleBuilder.java:[38,52] incompatible types: inference variable T has incompatible bounds
    equality constraints: capture#1 of ?
    upper bounds: capture#2 of ?,java.lang.Object

I also tried the following bindings:

for (Map.Entry<? extends Object,Object> e: instances.entrySet()) {
  bind(e.getKey()).toInstance(e.getValue());
}

Or

for (Map.Entry<? extends Object,Object> e: instances.entrySet()) {
  bind(e.getKey()).toInstance(e.getKey().cast(e.getValue()));
}

But none compile.

Upvotes: 1

Views: 829

Answers (1)

Olivier Gr&#233;goire
Olivier Gr&#233;goire

Reputation: 35477

I got rid of the generics and it worked:

    @Override protected void configure() {
      for (Class type : instances.keySet()) {
        bind(type).toInstance(instances.getInstance(type));
      }
    }

Upvotes: 2

Related Questions