如何在 F# 中获取给定联合类型的每个联合案例的类型

How to get the type of each union case for a given union type in F#

我在下面的 F# 代码中想知道如何通过反射获取与每个联合案例关联的类型

type AccountCreatedArgs = {
    Owner: string
    AccountId: Guid
    CreatedAt: DateTimeOffset
    StartingBalance: decimal
}

type Transaction = {
    To: Guid
    From: Guid
    Description: string
    Time: DateTimeOffset
    Amount: decimal
}

type AccountEvents =
    | AccountCreated of AccountCreatedArgs
    | AccountCredited of Transaction
    | AccountDebited of Transaction

我尝试使用 FSharpType.GetUnionCases(typeof<AccountEvents>)UnionCaseInfo 没有提供任何关于案例类型的信息(只有声明类型又名 AccountEvents 所以对我来说不是很有用)=/


glennsl 的回答对我很有帮助

我真正发现对我的情况有用的是:

let getUnionCasesTypes<'T> =
    Reflection.FSharpType.GetUnionCases(typeof<'T>)
    |> Seq.map (fun x -> x.GetFields().[0].DeclaringType)

UnionCaseInfo 有一个 GetFields 方法,它 returns 一个 PropertyInfo 的数组,它描述了联合案例的每个 field/argument。例如:

FSharpType.GetUnionCases(typeof<AccountEvents>)
    |> Array.map(fun c -> (c.Name, c.GetFields()))
    |> printfn "%A"

将打印

[|("AccountCreated", [|AccountCreatedArgs Item|]);
  ("AccountCredited", [|Transaction Item|]);
  ("AccountDebited", [|Transaction Item|])|]

分配给单个字段联合案例的名称是"Item",如果多个是"Item1","Item2"等。字段类型本身可以从[=17中检索=] 属性 个 PropertyInfo,所以:

FSharpType.GetUnionCases(typeof<AccountEvents>)
    |> Array.map(fun c -> (c.Name, c.GetFields() |> Array.map(fun p -> p.PropertyType.Name)))
    |> printfn "%A"

将因此打印

[|("AccountCreated", [|"AccountCreatedArgs"|]);
  ("AccountCredited", [|"Transaction"|]);
  ("AccountDebited", [|"Transaction"|])|]