微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

转换数据对象 - F#、Fabulous、sql-net-pcl 和 Web API 客户端库

如何解决转换数据对象 - F#、Fabulous、sql-net-pcl 和 Web API 客户端库

我对 F# 非常陌生,并试图找出在相似但不同的数据对象之间进行转换的最佳方法,同时最大限度地减少代码重复。我正在使用适用于 Xamarin Forms 的 Fabulous F# MVU 框架编写应用程序。

我使用 sqlite-net-pcl 进行数据持久化,它在创建数据库表并与该表交互时调用一个对象,并且我创建了一个 AuthorObject

    type AuthorObject() =
        [<PrimaryKey>] // sqlite-net-pcl attribute
        member val AuthorId = 0 with get,set
        member val Username = "" with get,set
        member val Token = "" with get,set

Fabulous 为模型使用记录类型,我创建了一个 Author 记录类型以在 Fabulous 内部传递:

    type Author = 
        { AuthorId: int
          Username: string
          Token: string }

但我还必须与返回 AuthorDetailDto 对象的 Web 服务 API 库(用 C# 编写)交互。 AuthorDetailDto 具有与上面相同的命名属性,另外还有更多我不需要担心的。我无法更改 AuthorDetailDto 的定义。

所以目前的限制似乎是 sqlite-net-pcl 需要一个带有成员的对象,Fabulous 需要一个记录类型,而我有这个 AuthorDetailDto 对象来自服务 API 客户端库,我可以'改变。我需要在这些类型之间进行转换,我最初希望我能逃脱:

    let convertToObject author = // Was hoping author param here Could be generic in some way
        let obj = AuthorObject()
        obj.AuthorId <- author.AuthorId
        obj.Username <- author.Username
        obj.Token <- author.Token
        obj

    let convertToModel (obj: AuthorObject) : Author =
        { AuthorId = obj.AuthorId
          Username = obj.Username
          Token = obj.Token }

但是随着 AuthorDetailDto增加,我发现我现在需要做这样的事情来让编译器满意:

    let convertAuthorDetailDtoToObject (dto: AuthorDetailDto) =
        let obj = AuthorObject()
        obj.AuthorId <- dto.AuthorId
        obj.Username <- dto.Username
        obj.Token <- dto.Token
        obj

    let convertAuthorToObject (author: Author) =
        let obj = AuthorObject()
        obj.AuthorId <- author.AuthorId
        obj.Username <- author.Username
        obj.Token <- author.Token
        obj

    let convertToModel (obj: AuthorObject) : Author =
        { AuthorId = obj.AuthorId
          Username = obj.Username
          Token = obj.Token }

以下是一些源文件

域模型.fs:

namespace MyApp.Mobile

module DomainModels =
    type Author = 
        { AuthorId: int
          Username: string
          Token: string }

作者.fs:

namespace MyApp.Mobile.Repository

open sqlite
open Client // Provides AuthorDetailDto.
open MyApp.Mobile.DomainModels

module Author =
    type AuthorObject() =
        [<PrimaryKey>]
        member val AuthorId = 0 with get,set

    let convertToObject author =
        let obj = AuthorObject()
        obj.AuthorId <- author.AuthorId
        obj.Username <- author.Username
        obj.Token <- author.Token
        obj

    let convertToModel (obj: AuthorObject) : Author =
        { AuthorId = obj.AuthorId
          Username = obj.Username
          Token = obj.Token }

    let connect dbPath = async {
            let db = sqliteAsyncConnection(sqliteConnectionString dbPath)
            do! db.CreateTableAsync<AuthorObject>() |> Async.AwaitTask |> Async.Ignore
            return db
    }

    let purgeLoggedInAuthor dbPath = async {
        let! db = connect dbPath
        do! db.ExecuteAsync "DELETE FROM AuthorObject" |> Async.AwaitTask |> Async.Ignore
    }

    let insertLoggedInAuthor dbPath author = async {
        let! db = connect dbPath
        do! db.InsertAsync (convertToObject author) |> Async.AwaitTask |> Async.Ignore
    }

初始调用如下所示:

insertLoggedInAuthor dbPath loggedInAuthor // loggedInAuthor is an AuthorDetailDto.

由于 Author.fs 中引用了这两种类型,因此错误FS0001 This expression was expected to have type 'DomainModels.Author' but here has type 'AuthorDetailDto'

我尝试过处理 inline 和静态成员约束,并尝试定义接口,但由于 Author 需要成为记录类型并且无法更改 {{1 }},这种方法似乎不可行。或者我可能只是对 F# 不够精通。

对于那些比我更熟悉 F# 的人,解决这种情况以最大程度地减少代码重复的最佳方法是什么?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。