David
David

Reputation: 11

How does Dagger2's built-in AssistedInject support factories that return interfaces instead of classes

I'm poking around with Dagger2 and its built-in AssisedInject annotation. The tutorial available at dagger.dev shows an example where the factory method returns a concrete class but I would have expected the factory to return an interface for which an implementation binding is defined in some module.

class MyDataService {
  @AssistedInject
  MyDataService(DataFetcher dataFetcher, @Assisted Config config) {}
}

// ---

@AssistedFactory
public interface MyDataServiceFactory {
  MyDataService create(Config config);
}

In Google Guice, e.g. I can create a module with a factory module builder to tie together interface and implementation:

install(new FactoryModuleBuilder()
     .implement(Payment.class, RealPayment.class)
     .build(PaymentFactory.class));

Isn't that possible with Dagger2 AssistedInject? I'm pretty new to Dagger, perhaps I misunderstood the concept at that point. Any help is very much appreciated!

Upvotes: 1

Views: 334

Answers (1)

Nikola Despotoski
Nikola Despotoski

Reputation: 50538

Yes it's possible:

Annotated your parameter that you want to be assisted, then declare a factory (can be abstract or interface) inside your concrete implementation that implements another Factory interface that returns the interface you want to bind, but now you return your concrete implementation by overriding the interface Factory return type

interface RequestSetFactory {
    fun create(address: String): RequestSet
}
class MyRequestSet @AssistedInject constructor(
    @Assisted private val deviceAddress: String,
) : RequestSet {

    @AssistedFactory
    abstract class Factory : RequestSetFactory {
        abstract override fun create(address : String): MyRequestSet
    }
    //.... impl code
}

In the binding module just add the mapping as:

@Module
abstract class RequestSetProviderBindingModule {

    @Binds
    @IntoMap
    @StringKey(Key.MY_KEY) //<-- change this 
    abstract fun bindMyRequests(my: MyRequestSet.Factory): RequestSetFactory
}

Declare the provider map in your instance factory as:


typealias RequestSetProviderMap = Map<String, @JvmSuppressWildcards Provider<RequestSetFactory>>

Upvotes: 0

Related Questions