mercredi 6 février 2019

How cast a generic value:'T to an array<'R> on F#

I'm building reflection for a JSON parser, and hit a road when serializing arrays:

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

The problem is (value:'T) is a record or a array of records, and can't see how enumerate them. I try with How to cast an object to a list of generic type in F# but not work:

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)

or

value :?> IEnumerable

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





Aucun commentaire:

Enregistrer un commentaire