如何正确序列化和反序列化字典的值?

时间:2014-02-11 04:49:28

标签: c# serialization

我正试图弄清楚如何正确行事。到目前为止,我正在使用此方法序列化对象列表:

var serializer = new System.Xml.Serialization.XmlSerializer(typeof(MyInfo));
using (var writer = new StreamWriter("SerializedValues.xml"))
{
    foreach (var o in dic.Values)
        serializer.Serialize(writer, o);
}

它变成了一个单独的XML文件列表,每个文件都有自己的标题,但都在一个文件中。我认为那是不对的。

然后我尝试反序列化它,它给了我以下错误:

  

意外的XML声明。 XML声明必须是文档中的第一个节点,并且不允许在其前面显示空白字符。第5行,第17位。

这正是下一个XML标头开始的地方。所以我猜我错了序列化。

还有一个问题来自反序列化返回单个对象的事实,这听起来已经错了,因为我期待一系列的排序。

如何正确序列化?

3 个答案:

答案 0 :(得分:1)

序列化整个字典怎么样?

编辑:好的,如何作为KeyValuePair的列表?

var list = dic.ToList();
XmlSerializer s = new XmlSerializer(list.GetType());
using (StreamWriter file = new StreamWriter("SerializedValues.xml"))
    s.Serialize(file, list);

答案 1 :(得分:0)

我设法通过在序列化之前将值转换为数组来实现这一目的:

var serializer = new System.Xml.Serialization.XmlSerializer(typeof(MyInfo[]));
using (var writer = new StreamWriter("SerializedValues.xml"))
{
    serializer.Serialize(writer, dic.Values.ToArray());
}

并将其反序列化:

using (var reader = new StreamReader("SerializedValues.xml"))
{
    var array = (MyInfo[])serializer.Deserialize(reader);
    foreach (var v in array)                
        dic[v.id] = v;
}           

答案 2 :(得分:0)

虽然你的解决方案适用于这个特定情况 - 因为Value也有关于Key的信息 - 我仍然会寻求更通用的解决方案。

即使Value没有关于密钥的信息,agentnega的修改后的答案也会起作用。

我最喜欢的是SerializableDictionary。因为(de)序列化没有额外的工作!取自这里: http://csharpcodewhisperer.blogspot.co.at/2013/06/namespace-xmlserializabledictionary.html

namespace XMLSerializableDictionary
{
  using System;
  using System.Collections.Generic;
  using System.Runtime.Serialization;
  using System.Xml;
  using System.Xml.Schema;
  using System.Xml.Serialization;

  [Serializable]
  [XmlRoot("Dictionary")]
  public class SerializableDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>, IXmlSerializable
  {
    private const string DefaultTagItem = "Item";
    private const string DefaultTagKey = "Key";
    private const string DefaultTagValue = "Value";
    private static readonly XmlSerializer KeySerializer =
                                    new XmlSerializer(typeof(TKey));

    private static readonly XmlSerializer ValueSerializer =
                                    new XmlSerializer(typeof(TValue));

    public SerializableDictionary() : base()
    {
    }

    protected SerializableDictionary(SerializationInfo info, StreamingContext context)
            : base(info, context)
    {
    }

    protected virtual string ItemTagName
    {
        get { return DefaultTagItem; }
    }

    protected virtual string KeyTagName
    {
        get { return DefaultTagKey; }
    }

    protected virtual string ValueTagName
    {
        get { return DefaultTagValue; }
    }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        bool wasEmpty = reader.IsEmptyElement;

        reader.Read();

        if (wasEmpty)
        {
         return;
        }

        try
        {
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                reader.ReadStartElement(this.ItemTagName);
                try
                {
                    TKey tKey;
                    TValue tValue;

                    reader.ReadStartElement(this.KeyTagName);
                    try
                    {
                        tKey = (TKey)KeySerializer.Deserialize(reader);
                    }
                    finally
                    {
                        reader.ReadEndElement();
                    }

                    reader.ReadStartElement(this.ValueTagName);
                    try
                    {
                        tValue = (TValue)ValueSerializer.Deserialize(reader);
                    }
                    finally
                    {
                        reader.ReadEndElement();
                    }

                    this.Add(tKey, tValue);
                }
                finally
                {
                    reader.ReadEndElement();
                }

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

    public void WriteXml(XmlWriter writer)
    {
        foreach (KeyValuePair<TKey, TValue> keyValuePair in this)
        {
            writer.WriteStartElement(this.ItemTagName);
            try
            {
                writer.WriteStartElement(this.KeyTagName);
                try
                {
                    KeySerializer.Serialize(writer, keyValuePair.Key);
                }
                finally
                {
                    writer.WriteEndElement();
                }

                writer.WriteStartElement(this.ValueTagName);
                try
                {
                    ValueSerializer.Serialize(writer, keyValuePair.Value);
                }
                finally
                {
                    writer.WriteEndElement();
                }
            }
            finally
            {
                writer.WriteEndElement();
            }
        }
    }
  }
}