Обеспечить всех детей класса кинжалом - PullRequest
0 голосов
/ 03 июля 2019

я создаю высокомодульное приложение, у меня есть много предложений, которые нужно вставить, все они являются дочерними (не прямыми) одного и того же класса, ни у одного из них нет параметров конструктора.

Я хочу избежать создания метода @Provides для каждого из них в моем модуле.

Есть ли способ сказать кинжалу, чтобы он автоматически предоставлял все классы, которые реализуют базовый интерфейс?Или это возможно сделать самому, используя отражение?

Я использую dagger-android с kotlin

Обновление : Я опубликую некоторый код для иллюстрации

В одном из модулей у меня есть этот интерфейс

interface ExampleClass: BaseExample {

    fun doSomething()

    }
}

Затем в основном приложении я реализую его

class ExampleClassImpl @Inject constructor() : ExampleClass { 
    override fun doSomething(){
    }
}

Класс, в котором я нуждаюсь, это Viewmodel, созданный с помощью кинжала, так что инъекция работаетна конструкторе.

class ExampleViewModel @Inject constructor(val exmpl :ExampleClass) : BaseViewModel { 

}

Я хочу внедрить этот ExampleClassImpl, для этого мне нужно создать модуль @ с методом, аннотированным @Provides или @Bind, и вернуть этот класс.

Без провайдера я получаю ошибку во время компиляции:

ошибка: [Dagger / MissingBinding] com.myapp.ExampleClassImpl не может быть предоставлен без аннотированного @ Provides метода.

1 Ответ

0 голосов
/ 08 июля 2019

Вы хотите ввести ExampleClass, но Кинжал знает только о ExampleClassImpl.Откуда Даггер узнает, что вы хотите этот конкретный подкласс?
Более того, вы говорите, что у вас есть много подклассов, которые вы хотите внедрить.Как Dagger узнает, какой из них предоставить конструктору, ожидающему базовый класс?

Если вы хотите, чтобы ExampleViewModel получил экземпляр ExampleClassImpl, вы можете просто изменить объявление на:

class ExampleViewModel @Inject constructor(val exmpl :ExampleClassImpl)

При этом вы теряете возможность поменять аргумент конструктора с другой реализацией ExampleClass.

Альтернативой может быть один метод @Named @Provides на подкласс.Так что-то вроде:

// In your module
@Provides
@Named("impl1")
fun provideExampleClassImpl1(impl: ExampleClassImpl): ExampleClass = impl
// When using the named dependency
class ExampleViewModel @Inject constructor(@Named("impl1") val exmpl :ExampleClass)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...