使用protobuf-net反序列化F#区分联合

时间:2015-11-04 12:58:31

标签: serialization f# protobuf-net discriminated-union

使用以下SO答案作为指导:Serializing F# discriminated unions with protobuf 我已经整理了一种序列化一个简单的F#区分联合的方法。不幸的是,我无法在不抛出stackoverflow exception的情况下序列化DU的第二个案例。我做错了什么?

CODE

open System
open System.IO
open System.Collections.Generic

open ProtoBuf

[<ProtoContract>]
[<ProtoInclude(100, "Program+DU+Good")>]
[<ProtoInclude(200, "Program+DU+Bad")>]
type DU = 
    | Good of bool
    | Bad of int
with
    override this.ToString() =
        match this with
        | Good i -> i.ToString()
        | Bad s -> s.ToString()


[<ProtoContract; Serializable>]
type Person(name:string, age:int, du:DU) = 
    let mutable name = name
    let mutable age = age
    let mutable du = du

    new() = Person("",0,Good true)

    [<ProtoMember(1)>]
    member this.Name 
        with get() = name
        and set(v) = name <- v

    [<ProtoMember(2)>]
    member this.Age 
        with get() = age
        and set(v) = age <- v

    [<ProtoMember(3)>]
    member this.DU
        with get() = du
        and set(v) = du <- v

    override this.ToString() = this.Name + ", " + this.Age.ToString() + ", " + this.DU.ToString()


[<EntryPoint>]
let main argv = 

    // typeof vs typedefof ?
    ProtoBuf.Meta.RuntimeTypeModel.Default.[typeof<DU>.GetNestedType("Good")].Add("item").UseConstructor <- false
    ProtoBuf.Meta.RuntimeTypeModel.Default.[typeof<DU>.GetNestedType("Bad")].Add("item").UseConstructor <- false
    //RuntimeTypeModel.Default.[typeof<DU>].CompileInPlace()    // doesn't seem to make any difference

    let p1 = Person("Sam", 38, Good false)
    let p2 = Person("Cand", 34, Bad 99)

    let filePath = @"C:\Temp\protocol.bin"

    if not (File.Exists filePath) then
        let fs = File.Create(filePath)
        fs.Close()

    use fileStream1 = new System.IO.FileStream(filePath, FileMode.Truncate, FileAccess.Write)
    ProtoBuf.Serializer.Serialize<Person>(fileStream1, p2)   // p1 does work because it uses the first case of the DU  
    fileStream1.Close()

    use fileStream2 = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read)
    let result = ProtoBuf.Serializer.Deserialize<Person>(fileStream2)      // stackoverflow exception ONLY for p2
    fileStream2.Close()

    printfn "%A" result
    Console.ReadLine() |> ignore
    0 // return an integer exit code

0 个答案:

没有答案