Как привести общее значение: 'T к массиву <' R> на F # - PullRequest
0 голосов
/ 07 февраля 2019

Я строю рефлексию для JSON-парсера и отправляюсь в путь при сериализации массивов:

let rec toJson (value:'T) =
    let t = typedefof<'T>

    match t with
    | _ when FSharpType.IsRecord(t) ->
        let fields = fieldsOf<'T>
        let values = seq {
            for field in fields do
                let x = field.GetValue value

                let result = toField field x
                yield field.Name.ToLower(), result
        }               
        values |> Seq.filter(fun (_, x) -> x <> Null) |> List.ofSeq 
        |> Chiron.JsonObject.ofPropertyList 
        |> Chiron.JsonObject.toJson
        |> Chiron.Formatting.Json.format
    | _ when t.IsArray ->
        let te = t.GetElementType()

        let values = value :? seq<obj> <-- How turn value into a array/seq?
        let txt = value :?> IEnumerable |> Seq.map toJson |> String.concat ""
        txt
    | _ ->
        _toField t value
        |> Chiron.Formatting.Json.format

let rows:Log.LogSyncRow array = query...

rows |> toJson

Проблема в том, что (value:'T) - это запись или массив записейи не вижу, как их перечислить.Я пытаюсь с Как привести объект к списку универсального типа в F # , но не работает:

let values = value :?> seq<obj> 

Error FS0008: This runtime coercion or type test from type    'T     to     seq<obj>    involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed. (FS0008) (Server)

или

value :?> IEnumerable

Error FS0033: The type 'System.Collections.Generic.IEnumerable<_>' expects 1 type argument(s) but is given 0 (FS0033) (Server)

1 Ответ

0 голосов
/ 07 февраля 2019

Проблема в том, что компилятор не знает, что такое 'T, и поэтому не знает, можно ли вообще 'T привести к IEnumerable<obj>.На самом деле есть некоторые типы, которые нельзя привести таким образом (вот что говорит вам компилятор: " Тесты типов во время выполнения не разрешены для некоторых типов ")

Но вы все равно можетезаставьте компилятор замолчать - сначала приведите к obj, затем приведите к тому, что вам нужно:

value :> obj :?> seq<obj>

Или, альтернативно, используйте встроенную функцию box, которая простото же приведение к obj, только в виде функции:

box value :?> seq<obj>
...