使用泛型的对象转换
Object conversion using generics
我确实有一个对象转换任务让我感到困惑 ;)
假设我有三种(或更多)格式的业务对象
class MapA { /*some implementation */ }
class MapB { /*some implementation */ }
class MapC { /*some implementation */ }
此外,我还有一个 "super object" 存储在数据库中,其中包含 MapA、MapB 和 MapC 的所有属性的超集。
class SuperMap { /* all implemented properties from all maps */ }
我现在需要能够与任何地图类型相互转换。所以我的想法是指定一个特定的Converter接口,将特定的地图转换为超级地图。
interface Converter<F>{
fun convertFrom(map: F): SuperMap
fun convertTo(map: SuperMap): F
}
这几种地图类型的所有者只需实现地图类型<->超级地图
class MapAConverter: Converter<MapA> {
override fun convertFrom(map: MapA): SuperMap {
return SuperMap()
}
override fun convertTo(map: SuperMap): MapA {
return MapA()
}
}
/* more converters */
最后,我想到了一个服务,然后执行以下操作:
如果用户想把MapA转换成MapC,服务内部会转换MapA -> SuperMap -> MapC, ...
这样我就不必编写出所有可能的组合...
class ConverterService
{
private val converters = mutableMapOf<KType, Converter<T>>()
fun <T>register(converter: Converter<T>){
this.converters[T::class] = converter
}
fun <F, T>Convert(map: F): T{
// F ... from map
val conv1 = converters[F::class]
if (conv1 == null)
throw Exception("No converter for this type of map")
// convert to super class
val sc = conv1.convertFrom(map)
// T ... to map
val conv2 = converters[T::class]
if(conv2 == null){
throw Exception("No converter for this type of map")
}
// convert to desirect class
return conv2.convertFrom(sc) as T
}
}
但这不起作用...
converters hashmap 不知道 T
val conv1 = converters[[=45=]] 告诉我 F::class 需要 reifeid 并希望将 Convert 转换为内联函数。如果我这样做,它会变得更加复杂......
我的实现思路是这样的:
fun main() {
// register some converters
var cs = ConverterService()
cs.register(MapAConverter())
cs.register(MapBConverter())
cs.register(MapCConverter())
// input is map a
val ma = MapA()
// i want map c
val mc = cs.Convert<MapA, MapC>(ma)
}
能以某种方式实现吗?我很高兴收到任何提示/建议。
谢谢!
使用mutableMapOf<KClass<*>, Converter<*>>()
(意思是Converter
with some unknown type parameter)。
如错误信息所述,您需要 F
和 T
为 reified 才能使用 F::class
:
inline fun <reified F, reified T> Convert(map: F): T { ... }
您在 register
中也需要它。我不确定你为什么认为它 "even more complicated".
您需要在 Convert
内部进行一些细微的更改:将转换器强制转换为具有正确的类型参数而不是 *
,并在末尾使用 convertTo
。我会做一个辅助函数
private inline fun <reified T> converter(): Converter<T> {
val result = converters[T::class]
if (result == null)
throw Exception("No converter for ${T::class.qualifiedName}")
else
return result as Converter<T>
}
inline fun <reified F, reified T> Convert(map: F): T {
// F ... from map
val conv1 = converter<F>()
// convert to super class
val sc = conv1.convertFrom(map)
// T ... to map
val conv2 = converter<T>()
// convert to desired class
return conv2.convertTo(sc)
}
我确实有一个对象转换任务让我感到困惑 ;) 假设我有三种(或更多)格式的业务对象
class MapA { /*some implementation */ }
class MapB { /*some implementation */ }
class MapC { /*some implementation */ }
此外,我还有一个 "super object" 存储在数据库中,其中包含 MapA、MapB 和 MapC 的所有属性的超集。
class SuperMap { /* all implemented properties from all maps */ }
我现在需要能够与任何地图类型相互转换。所以我的想法是指定一个特定的Converter接口,将特定的地图转换为超级地图。
interface Converter<F>{
fun convertFrom(map: F): SuperMap
fun convertTo(map: SuperMap): F
}
这几种地图类型的所有者只需实现地图类型<->超级地图
class MapAConverter: Converter<MapA> {
override fun convertFrom(map: MapA): SuperMap {
return SuperMap()
}
override fun convertTo(map: SuperMap): MapA {
return MapA()
}
}
/* more converters */
最后,我想到了一个服务,然后执行以下操作: 如果用户想把MapA转换成MapC,服务内部会转换MapA -> SuperMap -> MapC, ... 这样我就不必编写出所有可能的组合...
class ConverterService
{
private val converters = mutableMapOf<KType, Converter<T>>()
fun <T>register(converter: Converter<T>){
this.converters[T::class] = converter
}
fun <F, T>Convert(map: F): T{
// F ... from map
val conv1 = converters[F::class]
if (conv1 == null)
throw Exception("No converter for this type of map")
// convert to super class
val sc = conv1.convertFrom(map)
// T ... to map
val conv2 = converters[T::class]
if(conv2 == null){
throw Exception("No converter for this type of map")
}
// convert to desirect class
return conv2.convertFrom(sc) as T
}
}
但这不起作用...
converters hashmap 不知道 T
val conv1 = converters[[=45=]] 告诉我 F::class 需要 reifeid 并希望将 Convert 转换为内联函数。如果我这样做,它会变得更加复杂......
我的实现思路是这样的:
fun main() {
// register some converters
var cs = ConverterService()
cs.register(MapAConverter())
cs.register(MapBConverter())
cs.register(MapCConverter())
// input is map a
val ma = MapA()
// i want map c
val mc = cs.Convert<MapA, MapC>(ma)
}
能以某种方式实现吗?我很高兴收到任何提示/建议。
谢谢!
使用
mutableMapOf<KClass<*>, Converter<*>>()
(意思是Converter
with some unknown type parameter)。如错误信息所述,您需要
F
和T
为 reified 才能使用F::class
:inline fun <reified F, reified T> Convert(map: F): T { ... }
您在
register
中也需要它。我不确定你为什么认为它 "even more complicated".您需要在
Convert
内部进行一些细微的更改:将转换器强制转换为具有正确的类型参数而不是*
,并在末尾使用convertTo
。我会做一个辅助函数private inline fun <reified T> converter(): Converter<T> { val result = converters[T::class] if (result == null) throw Exception("No converter for ${T::class.qualifiedName}") else return result as Converter<T> } inline fun <reified F, reified T> Convert(map: F): T { // F ... from map val conv1 = converter<F>() // convert to super class val sc = conv1.convertFrom(map) // T ... to map val conv2 = converter<T>() // convert to desired class return conv2.convertTo(sc) }