Specific KClass из коллекции проекций Star - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь создать класс Synchronization, в который могут регистрироваться внешние модули, но я не могу заставить работать стандартную часть.

Внешние модули зарегистрируют SynchronizationBundle<SynchronizableType> на Synchronizator, который должен затем обрабатывать синхронизацию.

interface Synchronizable<T : Synchronizable<T>>

object SynchronizationBundles {
    val bundles: MutableMap<KClass<*>, SynchronizableBundle<*>> = mutableMapOf()

    fun <T : Synchronizable<T>> register(kClass: KClass<T>, bundle: SynchronizableBundle<T>) {
        bundles[kClass] = bundle
    }

    @Suppress("UNCHECKED_CAST")
    operator fun <T: Synchronizable<T>> get(kClass: KClass<T>) : SynchronizableBundle<T> {
        return bundles[kClass] as? SynchronizableBundle<T> ?: throw IllegalArgumentException("No bundle for ${kClass.simpleName}")
    }
}

Например, при операции синхронизация ондолжен перебирать зарегистрированные пакеты и уметь работать с конкретными реализациями Synchronizable<T>.Впереди псевдокод

fun synchronize() {
    bundles.forEach { bundleEntry ->
        val bundle = bundles[bundleEntry.key]
        val synchronizables = bundle.api.get()

        remoteSynchronizables.forEach { remoteSynchronizable ->
            val localSynchronizable = bundle.datastore.getByPlatformId(remoteSynchronizable.platformId)

            val synchronizableToInsert = bundle.conflictStrategy.resolve(localSynchronizable, remoteSynchronizable)

            synchronizableToInsert?.let {
                bundle.datastore.insert(it.withUploadStatus(UploadStatus.COMPLETED))
            }
        }
    }
}

Проблема в том, что val bundle = bundles[bundleEntry.key] возвращает SynchronizableBundle<*>, поэтому я не могу вызвать .conflictStrategy.resolve, поскольку он ожидает Synchronizable<T>

В качестве примераэто определение ConflictStrategy.Api и Datastore следуют одному и тому же шаблону

interface ConflictStrategy<T : Synchronizable<T>>

Возможно ли это вообще?Я уверен, что я не первый, кто попробует этот подход.

Если бы я мог как-то вызвать val bundle = bundles[MySynchronizable::class], я бы получил SynchronizableBundle<MySynchronizable>, но мне не удалось это сделать.Кроме того, типы Synchronizator будут работать с внешними модулями, поэтому я даже не знаю, сработает ли конкретный KClass.

Работа с функциями более высокого порядка, возможно, облегчит мою жизньи этот Синхронизатор может быть независимым от типа, но я не пробовал.

Спасибо!

1 Ответ

0 голосов
/ 06 декабря 2018

Далее я немного упростил код, чтобы продемонстрировать, как можно использовать этот менеджер пакетов извне:

object Bundles{
    private val bundles: MutableMap<KClass<*>, Bundle<*>> = mutableMapOf()

    fun <T>  register(c: KClass<T>, b: Bundle<T>){
        bundles[c]= b
    }

    operator fun <T> get(kClass: KClass<T>) : Bundle<T> {
        return bundles[kClass] as? Bundle<T> ?: throw IllegalArgumentException("No bundle for ${kClass.simpleName}")
    }

}

fun main(args: Array<String>) {
    Bundles.register(String::class, Bundle())
    Bundles.register(Int::class, Bundle())
    Bundles.register(Number::class, Bundle())

    val stringBundle = Bundles[String::class]
    val intBundle = Bundles[Int::class]
    val numBundle = Bundles[Number::class]
}

Вы уже заметили, что это работает.Теперь вы пытаетесь зациклить bundles внутри вашего SynchronizationBundles.На данный момент вы не можете знать, что было добавлено к bundles, и, следовательно, нет способа извлечь из него конкретные экземпляры.Я боюсь, что вы должны посмотреть на другие подходы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...