使用 Kotlin 映射模型 类

Mapping model classes with Kotlin

我正在寻找一种方法来改进应用中不同层的模型 class 之间的映射机制。

我已经为 classes 建模,它们是我在我的应用程序中使用的模型,在业务逻辑层(例如 Presenter)中。例如用户 class.

我有服务器端实体,这些是我用来通过 Retrofit 或任何其他技术反序列化来自服务器端端点的响应的实体。这些通常包含字段的 Gson 注释。例如 ApiUserResponse class.

我有 DTO 实体,这些实体代表我的应用程序中的数据库 table。我现在正在使用 Realm,但我使用过 ORMlite 和 Room。这些类型的 classes 还包含与数据库相关的注释。例如 UserDTO class.

我的缓存存储库(从数据库获取数据的那些)和我的网络存储库(从服务器端获取数据的那些)都公开了 RxJava 方法,返回包装在 Observable 中的响应 class es.

我现在正在做的解析 DTO 实体和服务器端实体是向 Observable class 添加一个扩展函数,它接收一个函数作为参数。这就是我用来将 DTO 和服务器端实体解析为模型 classes 的机制。例如:

myLoginRepository.getUser("someId")
    .mapTo(::myMappingFunction)

...

fun myMappingFunction(userResponse: ApiUserResponse): User {
    return User(userResponse.id, userResponse.name, userResponse.lastname)
}

在内部,mapTo 扩展函数所做的唯一一件事就是使用 flatMap 来扁平化 Observable 流并使用 map 来解析集合。

我认为这是实现模型相关 class 之间映射的一种很好的方法,但我正在寻找一种方法来改进它或做一些完全不同但需要较少编码的事情。显然这个例子非常简单,但目前我有一个 Mappings.kt 文件,每个新映射函数都在疯狂增长。

有什么建议吗?

您应该只有一个 class 代表网络中的实体和模型 class

如果你想为 Api 调用使用 Room 数据库和 Retrofit,你应该像这样使用

@Entity("tableName = something")
data class Something{

    @SerializedName("name")
    val name : String,
    @SerializedName("number")
    val number : Int}

也许 http://modelmapper.org/ 适合您。这样您就可以节省自己的映射函数,甚至可以指定一些复杂的映射函数。然而,它可能会在性能方面付出一些代价(看起来一直都是反射访问?)。

注:我自己还没有用过这个库,但看起来很有前途,值得推荐。在我帮助的最后一个项目中,他们构建了自己的模型映射器,这可能不是一个好主意(很多角落案例被遗忘,随后导致奇怪的行为或手动映射错误的字段;但是你的变体可能会受到影响那也是)。

刚刚找到另一篇关于映射框架及其性能的文章: http://www.baeldung.com/java-performance-mapping-frameworks 看起来不太适合 ModelMapper

您可能还只想生成映射函数。类似于你现在拥有的。或者只是使用实时模板?

手动编写映射迟早会引入您不再那么容易识别的错误,除非您对它们进行相应的测试。你做什么,对吗? ;-)

您可以使用转换器将 DTO 对象转换为实体,反之亦然。

Converter

ConversionService

你可以实现Converter接口,它是一个功能接口,你必须实现convert方法,然后将你的DTO转换为实体,你想转换它们的地方,你应该注入ConversionService并使用convert方法。