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

Eho*_*ret 2 reflection f# types discriminated-union

我想知道在下面的 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

Run Code Online (Sandbox Code Playgroud)

我尝试使用FSharpType.GetUnionCases(typeof<AccountEvents>)UnionCaseInfo没有提供任何关于案例类型的信息(只有声明类型,AccountEvents所以在我的案例中并不是真的有用)=/


glennsl 的回答真的帮助了我/sf/answers/3944586201/

在我的案例中,我真正觉得很方便的是:

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

gle*_*nsl 5

UnionCaseInfo有一个GetFields方法,它返回一个PropertyInfos数组,它描述了联合案例的每个字段/参数。例如:

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

将打印

[|("AccountCreated", [|AccountCreatedArgs Item|]);
  ("AccountCredited", [|Transaction Item|]);
  ("AccountDebited", [|Transaction Item|])|]
Run Code Online (Sandbox Code Playgroud)

分配给单个字段联合大小写的名称是“Item”,如果多个是“Item1”、“Item2”等。字段类型本身可以从 的PropertyType属性中检索PropertyInfo,因此:

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

将因此打印

[|("AccountCreated", [|"AccountCreatedArgs"|]);
  ("AccountCredited", [|"Transaction"|]);
  ("AccountDebited", [|"Transaction"|])|]
Run Code Online (Sandbox Code Playgroud)