Groostav
Groostav

Reputation: 3239

Using google guice with statically bound parameters

I would like to bind some parameters with guice in similar way that guice binds the unannotated Injector class to the calling injector instance for use with a provider.

In particular, on our project we have an object called the ResourceEnvironment, this object is effectively a wrapper on the method Class.getClassLoader().getResource(), enabling us to elegantly convert "com-paths" (class relative resource paths) into the resources they represent (FXML files, image files, etc). We use this to load resources that are deployed within our jar.

Right now, this code is repeated with a huge amount of frequency:

Class ClazzX{

  private final ResourceEnvironment env;

  @Inject
  public ClazzX(ResourceEnvironment.Factory envFactory){
    env = envFactory.create(this.getClass())
  }
}

when what I would really like to do is much more simply:

Class ClazzX{

  private @Inject ResourceEnvironment env;

}

but to do that, I would effectively need a provider:

binder.install(new Module(){

    @Provides ResourceEnvironment getResourceEnv(Injector callingInjector){
      Class targetClazz = callingInjector.getDependencyBeingResolved(); //not a real method
      ResourceEnivonment.Factory factory = callingInjector.getInstance(RE.F.class)
      return factory.create(targetClazz);
    }
});

Is it possible to get some information about the type currently being resolved through the injector at runtime?

Upvotes: 0

Views: 80

Answers (1)

Jan Galinski
Jan Galinski

Reputation: 12003

Using the custom injection of loggers as a template (https://github.com/google/guice/wiki/CustomInjections) it should be easy to implement a specific memberinjector that uses the declaring class as a source for the environment injection. From what I know, this requires a custom annotaion as well.

class ResourceEnvironmentMembersInjector<T> implements MembersInjector<T> {
   private final Field field;
   private final ResourceEnvironment  env;

   ResourceEnvironmentMembersInjector(Field field) {
     this.field = field;
     env = envFactory.create(field.getDeclaringClass());
     field.setAccessible(true);
  }

  public void injectMembers(T t) {
    try {
      field.set(t, env);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
}

Upvotes: 1

Related Questions