当前位置:  开发笔记 > 编程语言 > 正文

Serialize包含Dictionary成员的Class

如何解决《Serialize包含Dictionary成员的Class》经验,为你挑选了6个好方法。

扩展我之前的问题,我决定(de)序列化我的配置文件类,它运行得很好.

我现在想存储驱动器盘符映射关联数组(关键是驱动器号,值是网络路径)和使用都试过Dictionary,HybridDictionaryHashtable打电话时的这一点,但我总是得到下面的错误ConfigFile.Load()或者ConfigFile.Save():

反映类型'App.ConfigFile'时出错.[snip] System.NotSupportedException:无法序列化成员App.Configfile.mappedDrives [snip]

从我读过的词典和HashTables可以被序列化,所以我做错了什么?

[XmlRoot(ElementName="Config")]
public class ConfigFile
{
    public String guiPath { get; set; }
    public string configPath { get; set; }
    public Dictionary mappedDrives = new Dictionary();

    public Boolean Save(String filename)
    {
        using(var filestream = File.Open(filename, FileMode.OpenOrCreate,FileAccess.ReadWrite))
        {
            try
            {
                var serializer = new XmlSerializer(typeof(ConfigFile));
                serializer.Serialize(filestream, this);
                return true;
            } catch(Exception e) {
                MessageBox.Show(e.Message);
                return false;
            }
        }
    }

    public void addDrive(string drvLetter, string path)
    {
        this.mappedDrives.Add(drvLetter, path);
    }

    public static ConfigFile Load(string filename)
    {
        using (var filestream = File.Open(filename, FileMode.Open, FileAccess.Read))
        {
            try
            {
                var serializer = new XmlSerializer(typeof(ConfigFile));
                return (ConfigFile)serializer.Deserialize(filestream);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.ToString());
                return new ConfigFile();
            }
        }
    }
}

小智.. 178

Paul Welter的Weblog - XML Serializable Generic Dictionary有一个解决方案

出于某种原因,.net 2.0中的通用字典不是XML可序列化的.以下代码段是xml可序列化的通用字典.通过实现IXmlSerializable接口,字典是可序列化的.

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

[XmlRoot("dictionary")]
public class SerializableDictionary
    : Dictionary, IXmlSerializable
{
    public SerializableDictionary() { }
    public SerializableDictionary(IDictionary dictionary) : base(dictionary) { }
    public SerializableDictionary(IDictionary dictionary, IEqualityComparer comparer) : base(dictionary, comparer) { }
    public SerializableDictionary(IEqualityComparer comparer) : base(comparer) { }
    public SerializableDictionary(int capacity) : base(capacity) { }
    public SerializableDictionary(int capacity, IEqualityComparer comparer) : base(capacity, comparer) { }

    #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
}

+1.嘿,为什么Stack Overflow没有复制代码按钮?嗯?因为这段代码值得复制! (14认同)


bruno conde.. 73

您无法序列化实现IDictionary的类.看看这个链接.

问:为什么我不能序列化哈希表?

答:XmlSerializer无法处理实现IDictionary接口的类.这部分是由于计划约束,部分原因是哈希表在XSD类型系统中没有对应物.唯一的解决方案是实现一个不实现IDictionary接口的自定义哈希表.

所以我认为你需要为此创建自己的字典版本.检查另一个问题.



1> 小智..:

Paul Welter的Weblog - XML Serializable Generic Dictionary有一个解决方案

出于某种原因,.net 2.0中的通用字典不是XML可序列化的.以下代码段是xml可序列化的通用字典.通过实现IXmlSerializable接口,字典是可序列化的.

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

[XmlRoot("dictionary")]
public class SerializableDictionary
    : Dictionary, IXmlSerializable
{
    public SerializableDictionary() { }
    public SerializableDictionary(IDictionary dictionary) : base(dictionary) { }
    public SerializableDictionary(IDictionary dictionary, IEqualityComparer comparer) : base(dictionary, comparer) { }
    public SerializableDictionary(IEqualityComparer comparer) : base(comparer) { }
    public SerializableDictionary(int capacity) : base(capacity) { }
    public SerializableDictionary(int capacity, IEqualityComparer comparer) : base(capacity, comparer) { }

    #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
}


+1.嘿,为什么Stack Overflow没有复制代码按钮?嗯?因为这段代码值得复制!

2> bruno conde..:

您无法序列化实现IDictionary的类.看看这个链接.

问:为什么我不能序列化哈希表?

答:XmlSerializer无法处理实现IDictionary接口的类.这部分是由于计划约束,部分原因是哈希表在XSD类型系统中没有对应物.唯一的解决方案是实现一个不实现IDictionary接口的自定义哈希表.

所以我认为你需要为此创建自己的字典版本.检查另一个问题.


只是想知道`DataContractSerializer`类可以做到这一点.只是输出有点难看.

3> Despertar..:

而不是使用XmlSerializer你可以使用System.Runtime.Serialization.DataContractSerializer.这可以序列化字典和界面没有汗水.

以下是完整示例的链接,http://theburningmonk.com/2010/05/net-tips-xml-serialize-or-deserialize-dictionary-in-csharp/


最好的答案,亲自动手.

4> 小智..:

创建序列化代理.

例如,您有一个具有Dictionary类型的公共属性的类.

要支持此类型的Xml序列化,请创建一个通用键值类:

public class SerializeableKeyValue
{
    public T1 Key { get; set; }
    public T2 Value { get; set; }
}

将XmlIgnore属性添加到原始属性:

    [XmlIgnore]
    public Dictionary SearchCategories { get; set; }

公开数组类型的公共属性,它包含一个SerializableKeyValue实例数组,用于序列化和反序列化为SearchCategories属性:

    public SerializeableKeyValue[] SearchCategoriesSerializable
    {
        get
        {
            var list = new List>();
            if (SearchCategories != null)
            {
                list.AddRange(SearchCategories.Keys.Select(key => new SerializeableKeyValue() {Key = key, Value = SearchCategories[key]}));
            }
            return list.ToArray();
        }
        set
        {
            SearchCategories = new Dictionary();
            foreach (var item in value)
            {
                SearchCategories.Add( item.Key, item.Value );
            }
        }
    }



5> 小智..:

您应该探索Json.Net,非常容易使用,并允许直接在Dictionary中反序列化Json对象.

james_newtonking

例:

string json = @"{""key1"":""value1"",""key2"":""value2""}";
Dictionary values = JsonConvert.DeserializeObject>(json); 
Console.WriteLine(values.Count);
// 2
Console.WriteLine(values["key1"]);
// value1



6> David Schmit..:

字典和Hashtables不可序列化XmlSerializer.因此,您无法直接使用它们.解决方法是使用该XmlIgnore属性从序列化程序隐藏这些属性,并通过可序列化键值对列表公开它们.

PS:构建一个XmlSerializer非常昂贵,所以如果有可能重新使用它,请始终缓存它.

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有