Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2: How to inject Map<Class<? extends Foo>, Provider<? extends Foo>>

In Dagger 2, is it possible to inject a Map<Class<? extends Foo>, Provider<? extends Foo>>?

Suppose, I have a couple of classes that extends Foo

class Bar extends Foo {
    @Inject Bar() {}
}

class Baz extends Foo {
    @Inject Baz() {}
}

and now I want to create a FooFactory by declaring

class FooFactory {
    @Inject FooFactory(Map<Class<? extends Foo>, Provider<? extends Foo>> providers) {}
}

Can I do this in Dagger 2 with minimal configuration? I've read about Multibinding but I couldn't get it to work.

like image 221
Kirill Rakhman Avatar asked May 24 '17 16:05

Kirill Rakhman


People also ask

What is dagger injection?

Dagger is a fully static, compile-time dependency injection framework for Java, Kotlin, and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.

What is Multibinding dagger?

Dagger. Versions. Dagger allows you to bind several objects into a collection even when the objects are bound in different modules using multibindings. Dagger assembles the collection so that application code can inject it without depending directly on the individual bindings.

How does dagger generate code?

Dagger generates code similar to what you would have written manually. Internally, Dagger creates a graph of objects that it can reference to find the way to provide an instance of a class. For every class in the graph, Dagger generates a factory-type class that it uses internally to get instances of that type.


1 Answers

Answering my own question in accordance to the guidelines.


First, you have to get rid of the wildcard in Provider<? extends Foo>.

Second, you need to declare an annotation for the map key:

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface FooKey {
    Class<? extends Foo> value();
}

Then, for each implementation of Foo you need to declare in your Module:

@Binds @IntoMap @FooKey(Bar.class)
abstract Foo bindBar(Bar bar)
like image 112
Kirill Rakhman Avatar answered Sep 29 '22 13:09

Kirill Rakhman