Как получить тип каждого случая объединения для данного типа объединения в F # - PullRequest
1 голос
/ 29 мая 2019

В коде 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 не предоставляет никакой информации о типе дела (только декларирующий тип aka AccountEvents, поэтому в моем случае это не очень полезно) = /


Ответ glennsl действительно помог мне https://stackoverflow.com/a/56351231/4636721

Что мне действительно пригодилось в моем случае, так это:

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

1 Ответ

4 голосов
/ 29 мая 2019

UnionCaseInfo имеет метод GetFields, который возвращает массив PropertyInfo с, который описывает каждое поле / аргумент случая объединения. Например:

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" и т. Д. Сам тип поля можно получить из свойства PropertyType 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"|])|]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...