版本容忍的XML序列化

时间:2012-05-31 19:24:35

标签: wpf xml serialization xml-serialization

Reader C#项目需要坚持~POCO才能归档。但我们正处于首次亮相,并且经常发生变化。我们的软件已被少数客户使用(持久化)。 出于多种原因,我更喜欢使用XML。

我检查了很多xml序列化库。

  • 许多lib存储特定类型和版本。我不需要那个。
  • 很多libs没有给我们自己序列化的可能性:即我们需要一个自定义加载/保存数据的接口(我看到很多优点**)
  • 有些lib强迫我们使用空构造函数
  • 有些图书馆只管理公共财产
  • 有些lib对类型有很多限制(不支持Dictionary,...)

**(加载/保存数据的界面的优点)

  • 更易于管理多个版本
  • 如果需要,可以进行硬编码转换(类x - >类y,...)
  • 更容易保留旧代码

我强烈认为,根据我的需要,我们可以通过使用旧方法更好地服务:有点像在C ++中反序列化。我认为通过手动添加字段和字段名称而不是使用属性,我们会更好地服务。

种类:

void XmlDeserialize(XmlReader xmlReader)
{
  xmlReader.Load((n)=>Version(n)); // or just: _version = xmlReader.LoadInt("Version"); 
  xmlReader.Load((n)=>Name(n));
  xmlReader.Load((n)=>EmployeeId(n));

    if (Version ==2)
                    …

    If (version == 3)
                    …

我发现最接近我需要的是:支持IExtensibleDataObject的DataContractSerializer,但是使用起来很麻烦。

我怀疑自己到处都没错?我不可能是唯一有这种需求的人(或者这个愿景)。为什么没有人为此写任何lib,我在某处错过了什么?

我的想法是错误的?你推荐什么?

2 个答案:

答案 0 :(得分:0)

你必须使用XML reader.load吗?更容易创建表示XML数据的业务对象,然后反序列化对象,如下所示(抱歉,我只发现了我的vb.net版本):

Public Shared Function ReadFromString(ByVal theString As String, ByVal encoding As System.Text.Encoding, ByVal prohibitDTD As Boolean) As T
        Dim theReturn As T = Nothing
        Dim s As System.Xml.Serialization.XmlSerializer
        s = New System.Xml.Serialization.XmlSerializer(GetType(T))

        Dim theBytes As Byte() = encoding.GetBytes(theString)
        Using ms As New IO.MemoryStream(theBytes)
            Using sTr As New StreamReader(ms, encoding)
                Dim sttng As New XmlReaderSettings
                'sttng.ProhibitDtd = prohibitDTD
                If Not prohibitDTD Then
                    sttng.DtdProcessing = DtdProcessing.Ignore
                    sttng.XmlResolver = Nothing
                Else
                    sttng.DtdProcessing = DtdProcessing.Prohibit
                End If
                Using r As XmlReader = XmlReader.Create(sTr, sttng)
                    theReturn = CType(s.Deserialize(r), T)
                End Using
            End Using
        End Using


        Return theReturn
    End Function

如果您愿意,可以使用事件摆脱xmlreadersettings和编码。但是这样你可以为每个版本保留不同的业务对象吗?此外,如果您只是添加(而不是更改/删除)对象,您仍然可以为所有版本使用最新的业务对象,只需忽略缺少的字段。

答案 1 :(得分:0)

我最终决定像这样使用XmlSerialization usage但我讨厌被迫创建默认构造函数而无法序列化成员(私有或公共)。

我还决定在需要非常高的速度时使用ProtoContract。

但我首选的是DataContractSerializer,它提供xml格式(更容易调试),不需要默认构造函数,可以序列化任何成员。