如何解决转换数据对象 - 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 举报,一经查实,本站将立刻删除。