IXmlSerializable字典问题 [英] IXmlSerializable Dictionary problem

查看:150
本文介绍了IXmlSerializable字典问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个通用的字典,实现 IXmlSerializable (信用到 Charles Feduke )。

I was trying to create a generic Dictionary that implements IXmlSerializable (credit to Charles Feduke).

这是我的审判:

Sub Main()
    Dim z As New SerializableDictionary(Of String, String)
    z.Add("asdf", "asd")
    Console.WriteLine(z.Serialize)
End Sub

结果:

<?xml version="1.0" encoding="utf-16"?><Entry key="asdf" value="asd" />

我在WriteXml方法之上放置了一个断点,我看到当它停止时,作者包含没有数据,IMHO应该包含根元素和xml声明。

I placed a breakpoint on top of the WriteXml method and I see that when it stops, the writer contains no data at all, and IMHO it should contain the root element and the xml declaration.

<Serializable()> _
Public Class SerializableDictionary(Of TKey, TValue) : Inherits Dictionary(Of TKey, TValue) : Implements IXmlSerializable
    Private Const EntryString As String = "Entry"
    Private Const KeyString As String = "key"
    Private Const ValueString As String = "value"
    Private Shared ReadOnly AttributableTypes As Type() = New Type() {GetType(Boolean), GetType(Byte), GetType(Char), GetType(DateTime), GetType(Decimal), GetType(Double), GetType([Enum]), GetType(Guid), GetType(Int16), GetType(Int32), GetType(Int64), GetType(SByte), GetType(Single), GetType(String), GetType(TimeSpan), GetType(UInt16), GetType(UInt32), GetType(UInt64)}
    Private Shared ReadOnly GetIsAttributable As Predicate(Of Type) = Function(t) AttributableTypes.Contains(t)
    Private Shared ReadOnly IsKeyAttributable As Boolean = GetIsAttributable(GetType(TKey))
    Private Shared ReadOnly IsValueAttributable As Boolean = GetIsAttributable(GetType(TValue))
    Private Shared ReadOnly GetElementName As Func(Of Boolean, String) = Function(isKey) If(isKey, KeyString, ValueString)

    Public Function GetSchema() As System.Xml.Schema.XmlSchema Implements System.Xml.Serialization.IXmlSerializable.GetSchema
        Return Nothing
    End Function

    Public Sub WriteXml(ByVal writer As XmlWriter) Implements IXmlSerializable.WriteXml
        For Each entry In Me
            writer.WriteStartElement(EntryString)

            WriteData(IsKeyAttributable, writer, True, entry.Key)
            WriteData(IsValueAttributable, writer, False, entry.Value)

            writer.WriteEndElement()
        Next
    End Sub

    Private Sub WriteData(Of T)(ByVal attributable As Boolean, ByVal writer As XmlWriter, ByVal isKey As Boolean, ByVal value As T)
        Dim name = GetElementName(isKey)

        If attributable Then
            writer.WriteAttributeString(name, value.ToString)
        Else
            Dim serializer As New XmlSerializer(GetType(T))
            writer.WriteStartElement(name)
            serializer.Serialize(writer, value)
            writer.WriteEndElement()
        End If
    End Sub

    Public Sub ReadXml(ByVal reader As XmlReader) Implements IXmlSerializable.ReadXml
        Dim empty = reader.IsEmptyElement

        reader.Read()
        If empty Then Exit Sub

        Clear()

        While reader.NodeType <> XmlNodeType.EndElement
            While reader.NodeType = XmlNodeType.Whitespace
                reader.Read()

                Dim key = ReadData(Of TKey)(IsKeyAttributable, reader, True)
                Dim value = ReadData(Of TValue)(IsValueAttributable, reader, False)

                Add(key, value)

                If Not IsKeyAttributable AndAlso Not IsValueAttributable Then reader.ReadEndElement() Else reader.Read()

                While reader.NodeType = XmlNodeType.Whitespace
                    reader.Read()
                End While
            End While

            reader.ReadEndElement()
        End While
    End Sub

    Private Function ReadData(Of T)(ByVal attributable As Boolean, ByVal reader As XmlReader, ByVal isKey As Boolean) As T
        Dim name = GetElementName(isKey)
        Dim type = GetType(T)

        If attributable Then
            Return Convert.ChangeType(reader.GetAttribute(name), type)
        Else
            Dim serializer As New XmlSerializer(type)

            While reader.Name <> name
                reader.Read()
            End While

            reader.ReadStartElement(name)
            Dim value = serializer.Deserialize(reader)
            reader.ReadEndElement()

            Return value
        End If
    End Function

    Public Shared Function Serialize(ByVal dictionary As SerializableDictionary(Of TKey, TValue)) As String
        Dim sb As New StringBuilder(1024)
        Dim sw As New StringWriter(sb)
        Dim xs As New XmlSerializer(GetType(SerializableDictionary(Of TKey, TValue)))

        xs.Serialize(sw, dictionary)
        sw.Dispose()
        Return sb.ToString
    End Function

    Public Shared Function Deserialize(ByVal xml As String) As SerializableDictionary(Of TKey, TValue)
        Dim xs As New XmlSerializer(GetType(SerializableDictionary(Of TKey, TValue)))
        Dim xr As New XmlTextReader(xml, XmlNodeType.Document, Nothing)
        xr.Close()
              Return xs.Deserialize(xr)
    End Function

    Public Function Serialize() As String
        Dim sb As New StringBuilder
        Dim xw = XmlWriter.Create(sb)
        WriteXml(xw)
        xw.Close()
        Return sb.ToString
    End Function

    Public Sub Parse(ByVal xml As String)
        Dim xr As New XmlTextReader(xml, XmlNodeType.Document, Nothing)
        ReadXml(xr)
        xr.Close()
    End Sub

End Class


推荐答案

为什么它包含根?您不是在序列化中添加一个,您可以在其中创建 XmlWriter ...我想知道你应该有什么东西更多(C#,对不起):

Why would it contain a root? You aren't adding one in Serialize, where you create the XmlWriter... I wonder if you should have something more like (C#, sorry):

public string Serialize() {
    StringBuilder sb = new StringBuilder();
    XmlSerializer ser = new XmlSerializer(
        typeof(SerializableDictionary<TKey, TValue>));
    using (XmlWriter writer = XmlWriter.Create(sb)) {
        ser.Serialize(writer, this);
    }
    return sb.ToString();
}

这使用常规的 XmlSerializer 核心为写外部元素的东西。或者,更改序列化以包含您选择的外部元素。

This uses the regular XmlSerializer core for things like writing the outer element(s). Alternatively, change Serialize to include an outer element of your choosing.

这篇关于IXmlSerializable字典问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆