如何结合PassengerBuilder与TripBuilder实现复杂对象图的计算表达式构建
结合PassengerBuilder与TripBuilder构建嵌套对象图
咱们一步一步来实现这个需求,先从基础的类型定义开始,再分别构建两个Computation Expression Builder,最后完成嵌套使用的逻辑。
首先明确核心的记录类型,定义好Passenger和Trip的结构:
type Trip = { Destination: string DepartureDate: DateTime Duration: int // 行程天数 } type Passenger = { Name: string Age: int Trips: Trip list }
接下来先实现TripBuilder,用自定义操作让行程配置的语法更直观:
type TripBuilder() = // 初始化空的Trip状态 member _.Yield(_) = { Destination = ""; DepartureDate = DateTime.MinValue; Duration = 0 } // 自定义操作:设置目的地 [<CustomOperation("destination")>] member _.SetDestination(trip, dest) = { trip with Destination = dest } // 自定义操作:设置出发日期 [<CustomOperation("departureDate")>] member _.SetDepartureDate(trip, date) = { trip with DepartureDate = date } // 自定义操作:设置行程时长 [<CustomOperation("duration")>] member _.SetDuration(trip, days) = { trip with Duration = days } // 创建TripBuilder实例,方便后续使用 let trip = TripBuilder()
然后是核心的PassengerBuilder,重点要实现能嵌入TripBuilder计算表达式的操作,把构建好的Trip关联到Passenger上:
type PassengerBuilder() = // 初始化空的Passenger状态 member _.Yield(_) = { Name = ""; Age = 0; Trips = [] } // 自定义操作:设置乘客姓名 [<CustomOperation("name")>] member _.SetName(passenger, name) = { passenger with Name = name } // 自定义操作:设置乘客年龄 [<CustomOperation("age")>] member _.SetAge(passenger, age) = { passenger with Age = age } // 核心操作:添加单个行程,直接接收TripBuilder的计算表达式 [<CustomOperation("addTrip")>] member _.AddSingleTrip(passenger, tripExpr) = let builtTrip = tripExpr // 执行Trip的计算表达式,得到完整Trip实例 { passenger with Trips = builtTrip :: passenger.Trips } // 可选扩展:批量添加行程 [<CustomOperation("addTrips")>] member _.AddMultipleTrips(passenger, tripExprs) = let builtTrips = tripExprs |> List.map (fun expr -> expr) { passenger with Trips = builtTrips @ passenger.Trips } // 创建PassengerBuilder实例 let passenger = PassengerBuilder()
现在你就能用想要的流畅语法来构建带行程的Passenger记录了:
let alice = passenger { name "Alice" age 30 addTrip (trip { destination "Paris" departureDate (DateTime(2024, 7, 1)) duration 7 }) addTrip (trip { destination "Tokyo" departureDate (DateTime(2024, 10, 15)) duration 10 }) } // 验证结果 printfn "%A" alice
关键细节说明
- 两个Builder都通过
Yield方法初始化空的记录状态,再通过自定义操作逐步修改状态,符合Computation Expression的设计逻辑 - PassengerBuilder的
addTrip操作直接接收TripBuilder的计算表达式,执行后就能得到完整的Trip实例,再把它追加到Passenger的Trips列表中 - 这种嵌套写法既保持了代码的可读性,又能灵活构建复杂的对象图
内容的提问来源于stack exchange,提问作者Fede
相关产品推荐
相关产品推荐

