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