繁体   English   中英

如何序列化字典 <int, string> ?

[英]How do I serialize a Dictionary<int, string>?

如何序列化C# Dictionary<int, string>

这是一个简单的演示:

var lookup = new Dictionary<int, string>();

lookup.Add(1, "123");
lookup.Add(2, "456");

using (var ms = new MemoryStream())
{
    var formatter = 
       new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

    formatter.Serialize(ms, lookup);
    lookup = null;

    ms.Position = 0;
    lookup = (Dictionary<int, string>) formatter.Deserialize(ms);
}

foreach(var i in lookup.Keys)
{
    Console.WriteLine("{0}: {1}", i, lookup[i]);
}

但是您可能必须更加具体。

假设您正在谈论XML序列化,可以按照Kevin的建议使用Paul Welter的SerializableDictionary类,但这是另一种解决方案,不涉及IXmlSerializable的定制实现。

我的想法是,字典可以看作是键值对的集合。 XmlSerializer可以序列化一个集合,并且可以序列化一个键值对。 因此,您只需要为字典创建一个包装器即可,它看起来XmlSerializer一个集合,以便XmlSerializer可以毫无抱怨地处理它。

这是我的实现:

一个XmlDictionaryEntry类,用于保存键/值对( KeyValuePair<TKey, TValue>类无法序列化为XML,因为其属性是只读的)

public class XmlDictionaryEntry<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
}

XmlDictionaryEntryCollection类,实现键-值对的集合并使用字典来存储它们

public class XmlDictionaryEntryCollection<TKey, TValue> : ICollection<XmlDictionaryEntry<TKey, TValue>>
{
    public XmlDictionaryEntryCollection()
    {
        this.Dictionary = new Dictionary<TKey, TValue>();
    }

    public XmlDictionaryEntryCollection(IDictionary<TKey, TValue> dictionary)
    {
        dictionary.CheckArgumentNull("dictionary");
        this.Dictionary = dictionary;
    }

    [XmlIgnore]
    public IDictionary<TKey, TValue> Dictionary { get; private set; }

    #region ICollection<XmlDictionaryEntry<TKey,TValue>> Members

    public void Add(XmlDictionaryEntry<TKey, TValue> item)
    {
        this.Dictionary.Add(item.Key, item.Value);
    }

    public void Clear()
    {
        this.Dictionary.Clear();
    }

    public bool Contains(XmlDictionaryEntry<TKey, TValue> item)
    {
        return this.Dictionary.ContainsKey(item.Key);
    }

    public void CopyTo(XmlDictionaryEntry<TKey, TValue>[] array, int arrayIndex)
    {
        int index = arrayIndex;
        if (arrayIndex + this.Dictionary.Count > array.Length)
            throw new ArgumentException(ExceptionMessages.CopyToNotEnoughSpace);

        foreach (var kvp in this.Dictionary)
        {
            var entry = new XmlDictionaryEntry<TKey, TValue>
            {
                Key = kvp.Key,
                Value = kvp.Value
            };
            array[index++] = entry;
        }
    }

    public int Count
    {
        get { return this.Dictionary.Count; }
    }

    public bool IsReadOnly
    {
        get { return this.Dictionary.IsReadOnly; }
    }

    public bool Remove(XmlDictionaryEntry<TKey, TValue> item)
    {
        return this.Dictionary.Remove(item.Key);
    }

    #endregion

    #region IEnumerable<XmlDictionaryEntry<TKey,TValue>> Members

    public IEnumerator<XmlDictionaryEntry<TKey, TValue>> GetEnumerator()
    {
        foreach (var kvp in this.Dictionary)
        {
            yield return new XmlDictionaryEntry<TKey, TValue>
            {
                Key = kvp.Key,
                Value = kvp.Value
            };
        }
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    #endregion
}

一种扩展方法,可以更轻松地创建包装器(利用泛型类型推断):

public static class XmlSerializationExtension()
{
    public static XmlDictionaryEntryCollection<TKey, TValue> AsXmlSerializable<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
    {
        if (dictionary != null)
            return new XmlDictionaryEntryCollection<TKey, TValue>(dictionary);
        else
            return null;
    }
}

使用方法如下:

假设您具有此属性:

public Dictionary<string, Foo> Foos { get; set; }

您只需要从序列化器中隐藏该属性(使用XmlIgnore属性),然后序列化XmlDictionaryEntryCollection

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

[XmlElement("Foos")]
public XmlDictionaryEntryCollection SerializableFoos
{
    get { return Foos.AsXmlSerializable(); }
    set { Foos = value.Dictionary; }
}

相对于SerializableDictionary类,此技术的主要优点在于,它使您可以使用所需的任何种类的字典,而不必局限于特定的实现。

您可以编写自己的对象,该对象具有以下两种方法:序列化和反序列化。 Form_Load用于测试

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        Dictionary<int, string> list = new Dictionary<int, string>();

        list.Add(1, "one");
        list.Add(2, "two");
        list.Add(3, "three");

        Dictionary<int, string> list2 = Deserialize(Serialize(list));

    }

    public  string Serialize(Dictionary<int, string> classObject)
    {
        StringBuilder output = new StringBuilder();

        output.Append("<DictionaryIntString>");

        foreach (int key in classObject.Keys)
        {
            output.Append(String.Format("<Key value=\"{0}\">",key));
            output.Append(String.Format("<Value>{0}</Value></Key>", classObject[key]));

        }
        output.Append("</DictionaryIntString>");
        return output.ToString();


    }

    public Dictionary<int, string> Deserialize(string input)
    {
        Dictionary<int, string> output = new Dictionary<int, string>();

        XmlDocument xml = new XmlDocument();
        xml.LoadXml(input);

        foreach (XmlNode node in xml.GetElementsByTagName("Key"))
        {
            output.Add(Int32.Parse(node.Attributes["value"].InnerText),node.FirstChild.InnerText);

        }

        return output;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM