Dagger是否支持KClass<*>类型多绑定?如何实现该映射?
问题分析
问题根源在于JVM注解参数的类型限制:Kotlin的KClass<*>作为注解参数时,编译阶段会被自动转换为对应的Java Class<?>类型。Dagger处理Map多绑定时,会依据注解参数的JVM实际类型生成Map的键类型(即Class<*>),但你请求注入的是Map<KClass<*>, ...>,两者类型不匹配,导致Dagger无法识别绑定项。
解决方案
方案1:转换Class类型映射(推荐)
既然Class<*>作为键的映射可以正常工作,你可以通过一个额外的Provider将其转换为KClass<*>键的映射:
@Provides fun kClassSerializerMap( classBasedMap: Map<Class<*>, @JvmSuppressWildcards KSerializer<*>> ): Map<KClass<*>, @JvmSuppressWildcards KSerializer<*>> { return classBasedMap.mapKeys { entry -> entry.key.kotlin } }
之后直接注入转换后的Map即可:
@Inject lateinit var serializerMap: Map<KClass<*>, @JvmSuppressWildcards KSerializer<*>>
方案2:调整MapKey参数为Class类型
如果你想直接绑定生成Class<*>键的映射,再自行转换,可以修改MapKey注解:
@Target(AnnotationTarget.FUNCTION) @MapKey annotation class JsonSerializerKey(val value: Class<*>)
提供绑定的时候,用KClass.java获取对应的Class:
@Provides @IntoMap @JsonSerializerKey(MyData::class.java) fun provideMyDataSerializer(): KSerializer<MyData> = MyData.serializer()
再通过方案1的转换方法得到KClass<*>键的映射。
方案3:使用类名字符串作为MapKey参数(不推荐)
如果必须坚持用KClass作为注解参数的表象,可以改用类名字符串作为参数,再手动转换为KClass:
@Target(AnnotationTarget.FUNCTION) @MapKey annotation class JsonSerializerKey(val value: String)
提供绑定:
@Provides @IntoMap @JsonSerializerKey(MyData::class.qualifiedName!!) fun provideMyDataSerializer(): KSerializer<MyData> = MyData.serializer()
手动构建KClass键的映射:
@Provides fun kClassSerializerMap( stringBasedMap: Map<String, @JvmSuppressWildcards KSerializer<*>> ): Map<KClass<*>, @JvmSuppressWildcards KSerializer<*>> { return stringBasedMap.mapKeys { entry -> Class.forName(entry.key).kotlin } }
这种方法需要处理类加载异常,代码繁琐,仅作为特殊场景下的备选。
内容的提问来源于stack exchange,提问作者beigirad
相关产品推荐
相关产品推荐

