2

I have an interface PaymentProvider:

interface PaymentProvider {
    fun pay(amount: Double): Boolean
}

Here is different implementations:

class PayPalPayment @AssistedInject constructor(
    private val payPalRepo: PayPalRepository,
    @Assisted private val paymentData: PaymentData
): PaymentProvider {

   @AssistedFactory
   interface Factory : PaymentProviderFactory

    override fun pay(amount: Double): Boolean {
       // some code
    }
}


  class CreditCardPayment(
        private val creditCardPaymentRepo: CreditCardPaymentRepository
    ): PaymentProvider {
        override fun pay(amount: Double): Boolean {
           // some code
        }
    }

Also I have PaymentManager class who should receive PaymentProvider.

class PaymentManager(
    private val paymentProvider:PaymentProvider
) {
    // some logic
}

I want this class not to know which specific implementation of the PaymentProvider interface it works with. For this I'm provide with dagger implementation using multibindings. Here is my code:

    @Binds
    @[IntoMap PaymentProviderKey(Keys.PAYPAL)]
    fun bindPayPalPayment (factory: PayPalPayment.Factory): PaymentProviderFactory

    @Binds
    @[IntoMap PaymentProviderKey(Keys.CREDIT_CARD)]
    fun bindCreditCardPayment (factory: CreditCardPayment.Factory): PaymentProviderFactory


   interface PaymentProviderFactory{
        fun create(key: PaymentProviderKey, paymentData: PaymentData): PaymentProvider 
    }

Now I have a map of factories, but I don't understand how to provide specific implementation of interface. I tried to provide PaymentProviderFactory:

  @Provides
    fun providePaymentManager(
        factory: PaymentProviderFactory
    ): PaymentManager = PaymentManager (
       factory
    )

and i get this kind of error:

Invalid return type: PaymentProvider. An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor.

Please, help me. I have a problem when using @AssistedInject, without it I provide map of PaymentProvider and then I provide factory to create concrete implementation:

@Provides
fun providePaymentProviderFactory(
    paymentProviders: Map<PaymentProviderKey, @JvmSuppressWildcards Provider<PaymentProvider>>
): PaymentProviderFactory=
    object : PaymentProviderFactory{
        override fun create(key: PaymentProviderKey): PaymentProvider? {
            val paymentProvider = paymentProviders[key]
            return paymentProvider?.get()
        }
    }

In this case everything works, however I need to use @AssistedInject because I need to pass the data that I receive at runtime.

testivanivan
  • 967
  • 13
  • 36

0 Answers0