如何从不使用XElement的自定义XML序列化/反序列化为`Dictionary <int,string>`?

myW*_*SON 45 .net c# xml mono

Dictionary<int, string>如何用XML中的键和值填充它

<items>
<item id='int_goes_here' value='string_goes_here'/>
</items>
Run Code Online (Sandbox Code Playgroud)

并使用XElement将其序列化为XML?

L.B*_*L.B 100

在临时item班的帮助下

public class item
{
    [XmlAttribute]
    public int id;
    [XmlAttribute]
    public string value;
}
Run Code Online (Sandbox Code Playgroud)

样本词典:

Dictionary<int, string> dict = new Dictionary<int, string>()
{
    {1,"one"}, {2,"two"}
};
Run Code Online (Sandbox Code Playgroud)

.

XmlSerializer serializer = new XmlSerializer(typeof(item[]), 
                                 new XmlRootAttribute() { ElementName = "items" });
Run Code Online (Sandbox Code Playgroud)

序列化

serializer.Serialize(stream, 
              dict.Select(kv=>new item(){id = kv.Key,value=kv.Value}).ToArray() );
Run Code Online (Sandbox Code Playgroud)

反序列化

var orgDict = ((item[])serializer.Deserialize(stream))
               .ToDictionary(i => i.id, i => i.value);
Run Code Online (Sandbox Code Playgroud)

-------------------------------------------------- ----------------------------

如果你改变主意,可以使用XElement来完成它.

序列化

XElement xElem = new XElement(
                    "items",
                    dict.Select(x => new XElement("item",new XAttribute("id", x.Key),new XAttribute("value", x.Value)))
                 );
var xml = xElem.ToString(); //xElem.Save(...);
Run Code Online (Sandbox Code Playgroud)

反序列化

XElement xElem2 = XElement.Parse(xml); //XElement.Load(...)
var newDict = xElem2.Descendants("item")
                    .ToDictionary(x => (int)x.Attribute("id"), x => (string)x.Attribute("value"));
Run Code Online (Sandbox Code Playgroud)


Sco*_*ain 29

Paul Welter的ASP.NET博客有一个可序列化的字典.但它不使用属性.我将在代码下面解释原因.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>, IXmlSerializable
{
    #region IXmlSerializable Members
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

首先,这个代码有一个问题.假设你从其他来源读了一本字典:

<dictionary>
  <item>
    <key>
      <string>key1</string>
    </key>
    <value>
      <string>value1</string>
    </value>
  </item>
  <item>
    <key>
      <string>key1</string>
    </key>
    <value>
      <string>value2</string>
    </value>
  </item>
</dictionary>
Run Code Online (Sandbox Code Playgroud)

这将在de-seariazation上抛出异常,因为你只能有一个字典的键.


您必须在序列化字典中使用XElement的原因是字典未定义为Dictionary<String,String>字典Dictionary<TKey,TValue>.

要查看问题,请问自己:让我们说我们有一个TValue序列化到使用Elements的东西,它将自己描述为XML(比如字典词典Dictionary<int,Dictionary<int,string>>(不是模式的罕见,它是一个查找表)),如何您的仅属性版本是否完全代表属性内的字典?

  • 您通过调用"ReadXml"方法反序列化. (4认同)

Man*_*ert 6

默认情况下,字典在C#中不是Serializable,我不知道为什么,但它似乎是一个设计选择.

现在,我建议使用Json.NET将其转换为JSON并从那里转换为字典(反之亦然).除非你真的需要XML,否则我建议你完全使用JSON.

  • 据我所知,他想将XML序列化为字典.如果Dictionary是可序列化的,你可以使用像XmlSerializer这样的内置类来完成任务,但正如我所说,它不是. (4认同)

xme*_*eko 6

我有一个结构KeyValuePairSerializable

[Serializable]
public struct KeyValuePairSerializable<K, V>
{
    public KeyValuePairSerializable(KeyValuePair<K, V> pair)
    {
        Key = pair.Key;
        Value = pair.Value;
    }

    [XmlAttribute]
    public K Key { get; set; }

    [XmlText]
    public V Value { get; set; }

    public override string ToString()
    {
        return "[" + StringHelper.ToString(Key, "") + ", " + StringHelper.ToString(Value, "") + "]";
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,属性的 XML 序列化Dictionary如下:

[XmlIgnore]
public Dictionary<string, string> Parameters { get; set; }

[XmlArray("Parameters")]
[XmlArrayItem("Pair")]
[DebuggerBrowsable(DebuggerBrowsableState.Never)] // not necessary
public KeyValuePairSerializable<string, string>[] ParametersXml
{
    get 
    { 
        return Parameters?.Select(p => new KeyValuePairSerializable<string, string>(p)).ToArray(); 
    }
    set
    {
        Parameters = value?.ToDictionary(i => i.Key, i => i.Value);
    }
}
Run Code Online (Sandbox Code Playgroud)

只是属性必须是数组,而不是列表。