扩展我之前的问题,我决定(de)序列化我的配置文件类,它运行得很好.
我现在想存储驱动器盘符映射关联数组(关键是驱动器号,值是网络路径)和使用都试过Dictionary
,HybridDictionary
和Hashtable
打电话时的这一点,但我总是得到下面的错误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 DictionarymappedDrives = 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接口的自定义哈希表.
所以我认为你需要为此创建自己的字典版本.检查另一个问题.
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 }
您无法序列化实现IDictionary的类.看看这个链接.
问:为什么我不能序列化哈希表?
答:XmlSerializer无法处理实现IDictionary接口的类.这部分是由于计划约束,部分原因是哈希表在XSD类型系统中没有对应物.唯一的解决方案是实现一个不实现IDictionary接口的自定义哈希表.
所以我认为你需要为此创建自己的字典版本.检查另一个问题.
而不是使用XmlSerializer
你可以使用System.Runtime.Serialization.DataContractSerializer
.这可以序列化字典和界面没有汗水.
以下是完整示例的链接,http://theburningmonk.com/2010/05/net-tips-xml-serialize-or-deserialize-dictionary-in-csharp/
创建序列化代理.
例如,您有一个具有Dictionary类型的公共属性的类.
要支持此类型的Xml序列化,请创建一个通用键值类:
public class SerializeableKeyValue{ public T1 Key { get; set; } public T2 Value { get; set; } }
将XmlIgnore属性添加到原始属性:
[XmlIgnore] public DictionarySearchCategories { 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 ); } } }
您应该探索Json.Net,非常容易使用,并允许直接在Dictionary中反序列化Json对象.
james_newtonking
例:
string json = @"{""key1"":""value1"",""key2"":""value2""}"; Dictionaryvalues = JsonConvert.DeserializeObject >(json); Console.WriteLine(values.Count); // 2 Console.WriteLine(values["key1"]); // value1
字典和Hashtables不可序列化XmlSerializer
.因此,您无法直接使用它们.解决方法是使用该XmlIgnore
属性从序列化程序隐藏这些属性,并通过可序列化键值对列表公开它们.
PS:构建一个XmlSerializer
非常昂贵,所以如果有可能重新使用它,请始终缓存它.