问题描述
我正在开发一个新系统,在该系统中我为我的实体使用强类型的 Id 值。为此,我遵循了我之前看到的推荐模式。代码似乎非常重复,我想简化它。
type PersonId = private PersonId of string
module PersonId =
let private prefix = "person"
let value (PersonId id) = id
let create (id: string) = PersonId(sprintf "%s_%s" prefix id)
type OrderId = private OrderId of string
module OrderId =
let private prefix = "order"
let value (OrderId id) = id
let create (id: string) = OrderId(sprintf "%s_%s" prefix id)
有没有办法让这段代码更通用,这样我就不必重复模块代码了?我正在考虑制作 EntityId
和 PersonId
类型的 OrderId
可区分联合,但不确定 EntityId
模块代码可能是什么样子。感谢您的帮助。
解决方法
我认为您正朝着这样的方向发展:
type EntityId =
private
| PersonId of string
| OrderId of string
module EntityId =
let init makeEntity prefix =
fun id -> makeEntity (sprintf "%s_%s" prefix id)
let value = function
| PersonId id
| OrderId id -> id
这里的技巧是使用 init
函数来创建您当前的 create
函数,如下所示:
module PersonId =
let create = EntityId.init PersonId "person"
module OrderId =
let create = EntityId.init OrderId "order"
然后你可以像这样使用它:
let personId = PersonId.create "abc"
let orderId = OrderId.create "xyz"
printfn "%A" personId
printfn "%A" orderId
printfn "%s" <| EntityId.value personId
printfn "%s" <| EntityId.value orderId
输出为:
PersonId person_abc
OrderId order_xyz
person_abc
order_xyz
附言如果你喜欢柯里化,你可以将 init
简化为:
let init makeEntity prefix id =
makeEntity (sprintf "%s_%s" prefix id)