2
我需要將使用F#區分的聯合表示的抽象語法樹保留爲人類可讀的緊湊格式,例如已經在F#語言中使用的格式來構造區分的聯合體,以便以後可以讀回歧視聯合實例。我對F#庫不支持這一點感到有點驚訝,因爲它肯定必須以編譯器和F#交互式的高效方式完成。我在哪裏可以找到F#歧視工會的序列化程序?
是否有任何免費/開放源代碼實現在合理的(但不一定非常有效)的方式做到這一點?
注意:我不想要基於XML的序列化。
我需要將使用F#區分的聯合表示的抽象語法樹保留爲人類可讀的緊湊格式,例如已經在F#語言中使用的格式來構造區分的聯合體,以便以後可以讀回歧視聯合實例。我對F#庫不支持這一點感到有點驚訝,因爲它肯定必須以編譯器和F#交互式的高效方式完成。我在哪裏可以找到F#歧視工會的序列化程序?
是否有任何免費/開放源代碼實現在合理的(但不一定非常有效)的方式做到這一點?
注意:我不想要基於XML的序列化。
編輯:下面的答案都不符合您的標準,但我張貼的情況下其他人尋找聯盟序列化發現他們有用。我不知道任何庫的方式,以重新解析聯合的sprintf "%A"
輸出 - 請記住,編譯器和FSI有一個很不同的任務,知道範圍和處理名稱空間和限定的名稱和陰影和什麼,甚至忽略這一點,解析工會(數據,字符串,任意對象等)攜帶的數據本身可能是一項完整的任務。
下面是聯盟序列化的一種策略,作爲一個小樣本程序的一部分。 (KnownTypeAttribute
可以採用方法名稱,並且可以使用一些反射來獲取類型。)這是向聯合添加一小段代碼以獲得序列化的一種非常簡單的方法。
open Microsoft.FSharp.Reflection
open System.Reflection
open System.Runtime.Serialization
open System.Xml
[<KnownType("KnownTypes")>]
type Union21WithKnownTypes =
| Case1 of int * int
| Case2 of string
static member KnownTypes() =
typeof<Union21WithKnownTypes>.GetNestedTypes(
BindingFlags.Public
||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion
let dcs = new DataContractSerializer(typeof<Union21WithKnownTypes[]>)
let arr = [| Case1(1,1); Case2("2") |]
printfn "orig data: %A" arr
let sb = new System.Text.StringBuilder()
let xw = XmlWriter.Create(sb)
dcs.WriteObject(xw, arr)
xw.Close()
let s = sb.ToString()
printfn ""
printfn "encoded as: %s" s
printfn ""
let xr = XmlReader.Create(new System.IO.StringReader(s))
let o = dcs.ReadObject(xr)
printfn "final data: %A" o
這裏的JSON版本:
open Microsoft.FSharp.Reflection
open System.Reflection
open System.Runtime.Serialization
open System.Runtime.Serialization.Json
open System.Xml
[<KnownType("KnownTypes")>]
type Union21WithKnownTypes =
| Case1 of int * int
| Case2 of string
static member KnownTypes() =
typeof<Union21WithKnownTypes>.GetNestedTypes(
BindingFlags.Public
||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion
let dcs = new DataContractJsonSerializer(typeof<Union21WithKnownTypes[]>)
let arr = [| Case1(1,1); Case2("2") |]
printfn "orig data: %A" arr
let stream = new System.IO.MemoryStream()
dcs.WriteObject(stream, arr)
stream.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore
let bytes = Array.create (int stream.Length) 0uy
stream.Read(bytes, 0, int stream.Length) |> ignore
let s = System.Text.Encoding.ASCII.GetString(bytes)
printfn ""
printfn "encoded as: %s" s
printfn ""
stream.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore
let o = dcs.ReadObject(stream)
printfn "final data: %A" o