2

这是我的程序 -

module Program
open System
open System.IO
open System.Text  
open System.Xml
open System.Xml.Serialization
open System.Runtime.Serialization
open System.Reflection
open Microsoft.FSharp.Reflection

let getUnionTypes<'a> () =
    let nestedTypes = typedefof<'a>.GetNestedTypes(BindingFlags.Public ||| BindingFlags.NonPublic) 
    Array.filter FSharpType.IsUnion nestedTypes

type Alpha =
    { X : int * int
      Y : Alpha option }

type [<KnownType "GetTypes">] Beta =
    | A of int * Alpha
    | B of Beta option
    | C of Map<int, Beta>
    static member GetTypes () = getUnionTypes<Beta> ()

let [<EntryPoint>] main _ =
    let alpha = { X = (0, 0); Y = Some { X = (1, 1); Y = None }}
    let betaA = A (0, alpha)
    let betaB = B (Some betaA)
    let betaC = C (Map.singleton 0 betaB)
    let sb = new StringBuilder()
    let xmlSerializer = DataContractSerializer(typeof<Beta>); 
    xmlSerializer.WriteObject(new XmlTextWriter(new StringWriter(sb)), betaC)
    let sr = sb.ToString()
    printfn "%A" sr
    0

这是输出 -

"<Program.Beta xmlns:i="http://www.w3.org/2001/XMLSchema-instance" i:type="Progr
am.Beta.C" xmlns="http://schemas.datacontract.org/2004/07/"><item xmlns:d2p1="ht
tp://schemas.datacontract.org/2004/07/Microsoft.FSharp.Collections"><d2p1:serial
izedData xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Collections.
Generic"><d3p1:KeyValuePairOfintProgram.BetalLTIrbuF><d3p1:key>0</d3p1:key><d3p1
:value i:type="Program.Beta.B"><item xmlns:d6p1="http://schemas.datacontract.org
/2004/07/Microsoft.FSharp.Core"><d6p1:value i:type="Program.Beta.A"><item1>0</it
em1><item2><X_x0040_ xmlns:d9p1="http://schemas.datacontract.org/2004/07/System"
><d9p1:m_Item1>0</d9p1:m_Item1><d9p1:m_Item2>0</d9p1:m_Item2></X_x0040_><Y_x0040
_><d6p1:value><X_x0040_ xmlns:d11p1="http://schemas.datacontract.org/2004/07/Sys
tem"><d11p1:m_Item1>1</d11p1:m_Item1><d11p1:m_Item2>1</d11p1:m_Item2></X_x0040_>
<Y_x0040_ i:nil="true" /></d6p1:value></Y_x0040_></item2></d6p1:value></item></d
3p1:value></d3p1:KeyValuePairOfintProgram.BetalLTIrbuF></d2p1:serializedData></i
tem></Program.Beta>"

我可以做哪些简单的事情来改进这个 XML 输出?我尝试了各种属性,但似乎都没有帮助。请注意,我需要保持我的数据结构不可变,并且我希望避免编写我自己的序列化库,或者尽可能将依赖项添加到另一个自制程序库。理想情况下,它应该是一个简单的解决方案。

4

2 回答 2

1

我可以做哪些简单的事情来改进这个 XML 输出?

.NET 对序列化的支持非常糟糕,需要很长时间才能生成非常冗长的易碎消息。我强烈建议不要使用它。

我写了一篇关于 F# 中的 XML 序列化的(非免费)文章。我使用反射来解构 F# 类型的任意值并将它们转换为 XML 并再次转换回来。性能比内置序列化器好得多,并且转换是结构性的而不是名义上的,因此您可以读回相同的类型定义(例如使用 F# 交互),但它仍然比 OCaml 的内置序列化等竞争对手慢得多。使用该文章中的代码,您只需执行以下操作:

> serialize betaC;;
val it : string =
  "<unionCase><name>C</name><map><keyValue><int>0</int><unionCase><name>B</name><unionCase><name>Some</name><unionCase><name>A</name><int>0</int><record><field><name>X</name><value><tuple><int>0</int><int>0</int></tuple></value></field><field><name>Y</name><value><unionCase><name>Some</name><record><field><name>X</name><value><tuple><int>1</int><int>1</int></tuple></value></field><field><name>Y</name><value><unionCase><name>None</name></unionCase></value></field></record></unionCase></value></field></record></unionCase></unionCase></unionCase></keyValue></map></unionCase>"
于 2013-08-05T22:42:41.327 回答
0

您可以在序列化后漂亮地打印结果字符串:

XDocument.Parse(sr).ToString()

这位于System.Xml.Linq程序集和命名空间中。

于 2013-08-03T07:07:38.733 回答