Dagger: Inject @Named strings?

It sounds like you have a Map<String, String> and you want to use something that binds these automatically to named strings. You cannot do that as automatically in Dagger as you can in Guice, since in Guice you can create a properties binder.

Dagger requires knowledge of all of your bindings at compile-time, in order to do the analysis to ensure that all bindings and dependencies are satisfied

That said, you could do something like this - it is more boiler plate, but it is legit.

@Module(library = true)
public class PropertiesModule {
  public final Properties props;

  PropertiesModule(Properties props) {
    this.props = props;
  }

  @Provides @Named("property.one") String providePropertyOne() {
    props.getProperty("property.one", "some default");
  }

  @Provides @Named("property.two") String providePropertyTwo() {
    props.getProperty("property.two", "some other default");
  }
  ...
}

This will allow for all of the bindings you need to be created, but to be satisfied from runtime values. The keys, however, are known at compile time (and must be, since you're using @Named("string literal") in your code anyway. Heck, if you have defined your property names and defaults as constant strings you can even do:

  @Provides @Named(PROPERTY_NAME_CONSTANT) String a() {
    props.getProperty(PROPERTY_NAME_CONSTANT, PROPERTY_NAME_CONSTANT_DEFAULT);
  }

It is more boiler plate, but Dagger has, while trying to eliminate much boiler plate, preferred compile-time analysis over absolute boiler plate reduction. That said, I'll propose a feature that will improve this situation, auto-generating a module for system properties from a known list, or some such. I think even this boiler plate can be reduced.


You have to define a provider in the dagger module for your @Named instance.

@Provides @Named("foo") String provideFoo()
{
    return "foo string";
}

Then you can inject the named instance in your constructor or using field injection in your dependent class.

public class Thermosiphon
{
    @Inject @Named("foo") String fooString;

    @Inject public Thermosiphon(Heater heater)
    {
        System.out.println("value of fooString is " + fooString);
    }
}