package expo.modules.kotlin.services import expo.modules.kotlin.AppContext import java.lang.ref.WeakReference class ServicesRegistry( private val appContextHolder: WeakReference ) { @PublishedApi internal val registry = mutableMapOf, Service>() fun register(serviceClass: Class) = apply { val appContext = requireNotNull(appContextHolder.get()) { "Cannot register a service to an invalid app context." } val service = Service.construct(serviceClass, appContext) for (serviceInterface in getServiceInterfaces(service)) { registry[serviceInterface] = service } } fun register(serviceClasses: List>) = apply { serviceClasses.forEach { serviceClass -> register(serviceClass) } } inline fun register() = register(T::class.java) fun register(service: Service) = apply { for (serviceInterface in getServiceInterfaces(service)) { registry[serviceInterface] = service } } fun register(serviceClass: Class, service: Service) = apply { registry[serviceClass] = service } private fun getServiceInterfaces(service: Service): List> { val serviceClass = service.javaClass val serviceInterfaces = serviceClass .getAnnotationsByType(ServiceInterface::class.java) .map { it.clazz.java } .takeIf { it.isNotEmpty() } ?: listOf(serviceClass) return serviceInterfaces } inline fun service(): T? { return registry[T::class.java] as? T } }