F# 映射到无模式匹配的联合事例构造函数
我有一个联合类型F# 映射到无模式匹配的联合事例构造函数,f#,F#,我有一个联合类型CustomerEvent如下: type CustomerRegisteredEvent = { CompanyName: string } type CustomerDeletedEvent = { DeletedOn: DateTimeOffset } type CustomerEvent = | CustomerRegistered of CustomerRegisteredEvent | CustomerDeleted of CustomerDeletedEv
CustomerEvent
如下:
type CustomerRegisteredEvent = { CompanyName: string }
type CustomerDeletedEvent = { DeletedOn: DateTimeOffset }
type CustomerEvent =
| CustomerRegistered of CustomerRegisteredEvent
| CustomerDeleted of CustomerDeletedEvent
let map (input: Events.IEvent): CustomerEvent =
match input with
| :? Events.IEvent<CustomerRegisteredEvent> as event ->
CustomerRegistered(event.Data)
| :? Events.IEvent<CustomerDeletedEvent> as event ->
CustomerDeleted(event.Data)
我还有一个map
函数,如下所示:
type CustomerRegisteredEvent = { CompanyName: string }
type CustomerDeletedEvent = { DeletedOn: DateTimeOffset }
type CustomerEvent =
| CustomerRegistered of CustomerRegisteredEvent
| CustomerDeleted of CustomerDeletedEvent
let map (input: Events.IEvent): CustomerEvent =
match input with
| :? Events.IEvent<CustomerRegisteredEvent> as event ->
CustomerRegistered(event.Data)
| :? Events.IEvent<CustomerDeletedEvent> as event ->
CustomerDeleted(event.Data)
let映射(输入:Events.IEvent):CustomerEvent=
匹配输入
| :? Events.IEvent作为事件->
CustomerRegistered(事件数据)
| :? Events.IEvent作为事件->
CustomerDeleted(事件数据)
可以看出,除了union案例的构造函数之外,这两条路径几乎相同
这可以用一种更通用的方式写吗?甚至可以不用使用模式匹配吗?这并不漂亮,但我认为这正是你想要的:
open FSharp.Reflection
let getCaseMap<'t> () =
FSharpType.GetUnionCases(typeof<'t>)
|> Seq.map (fun unionCase ->
let typ =
let property =
unionCase.GetFields() |> Seq.exactlyOne
property.PropertyType
let create data =
FSharpValue.MakeUnion(unionCase, [| data |])
:?> 't
typ.Name, create)
|> Map
let caseMap = getCaseMap<CustomerEvent> ()
let map (input: Events.IEvent) =
let typ =
input.GetType().GenericTypeArguments
|> Seq.exactlyOne
let data =
let property =
input.GetType().GetProperty("Data")
property.GetValue(input)
caseMap.[typ.Name] data
打开FSharp.Reflection
让我们来看看(案例地图)
|>Seq.map(案例->
let typ=
出租财产=
unionCase.GetFields()|>Seq.exactlyOne
property.PropertyType
让我们创建数据=
FSharpValue.MakeUnion(unionCase,[| data |])
:?>“t
类型名称,创建)
|>地图
让caseMap=getCaseMap()
let映射(输入:Events.IEvent)=
let typ=
input.GetType().GenericTypeArguments
|>Seq.exactlyOne
让数据=
出租财产=
input.GetType().GetProperty(“数据”)
property.GetValue(输入)
案例图。[典型名称]数据
这使用反射来避免模式匹配,而是执行映射查找来直接从给定事件的类型中查找正确的联合大小写。它假设DU遵循严格的模式,因此没有错误处理。您可能可以使用反射来实现这一点。这是一种你会考虑的方法吗?是的,反射会被代码从问题中取代,所有的东西似乎都起作用了。谢谢