简体   繁体   English

如何强制转换通用值:'T到F#上的array <'R>

[英]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: 我正在为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

The problem is (value:'T) is a record or a array of records, and can't see how enumerate them. 问题是(value:'T)是一个记录或记录的数组,看不到如何枚举它们。 I try with How to cast an object to a list of generic type in F# but not work: 我尝试使用如何在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)

or 要么

value :?> IEnumerable

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

The problem is that the compiler doesn't know what 'T is, and so doesn't know whether 'T is castable to IEnumerable<obj> at all. 问题是编译器根本不知道'T是什么,因此根本不知道'T是否可转换为IEnumerable<obj> There are actually some types that can't be cast like this (which is what the compiler tells you: " Runtime type tests are not allowed on some types ") 实际上,有些类型不能像这样强制转换(编译器告诉您:“ 某些类型不允许运行时类型测试 ”)

But you can still force the compiler to shut up about it - cast to an obj first, then cast to whatever you need: 但是您仍然可以强制编译器关闭它-首先强制转换为obj ,然后强制转换为所需的任何内容:

value :> obj :?> seq<obj>

Or, alternatively, use the built-in function box , which is just the same cast to obj , only wrapped as a function: 或者,或者使用内置函数box ,它与obj相同,仅包装为一个函数:

box value :?> seq<obj>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM