2010-11-11 8 views
3

У меня есть следующий класс:Как сериализовать класс, содержащий словарь?

[Serializable] 
public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public Dictionary<string, string> Attributes { get; set; } 
} 

Я хотел бы сериализации его с помощью XmlSerializer и получить следующий вывод:

<Person> 
    <FirstName>John</FirstName> 
    <LastName>Doe</LastName> 
    <Attributes> 
     <PhoneNumber>12345</PhoneNumber> 
     <StreetName>...</StreetName> 
     <StreetNumber>...</StreetNumber> 
     ... 
    </Attributes> 
</Person> 

Любая помощь будет оценена.

ответ

1

Я сделал это раньше:

/// <summary> 
    /// Save all information needed set current game state into given file. 
    /// </summary> 
    /// <param name="fileName"></param> 
    public void save(string fileName) 
    { 
    Dictionary<string, string> attributes = new Dictionary<string, string>(); 
    attributes.Add("blue", "very"); 
    attributes.Add("red", "not"); 

     Stream stream = File.Open(fileName, FileMode.Create); 
     BinaryFormatter bFormatter = new BinaryFormatter(); 

     // Request the current state of all registered 
// objects and save them into the file. 
    foreach (KeyValuePair<string, string> storeOnDisk in attributes) 
    bFormatter.Serialize(stream, storeOnDisk); 

     stream.Close(); 
    } 
2
 using System; 
     using System.Collections.Generic; 
     using System.Text; 
     using System.Xml.Serialization; 

     namespace CSharpSampleApplication.Data.CoreObjects 
     { 
      [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 

      } 
     } 
+0

Просто замените вашу декларацию Словарь -> SerializableDictionary. Он будет автоматически сериализован/десериализован – skaeff

0

Почему бы вам не использовать ProtocolBuffer сериализации. Это open source и бесплатный plataform, вы можете использовать его с Java, C++ и Python. Это подсказка.

2

Как и в ответ MrFox, это хак, который я использовал в прошлом, который работает достаточно хорошо.

public class Foo{ 

    [XmlIgnore()] 
    public Dictionary<string,string> Dct{get;set;} 

    [XmlAttribute] 
    public string SerializedDictionary{ 
      get{ 
       StringBuilder s = new StringBuilder(); 
       foreach(var kvp in Dct){ 
        if (s.Length > 0) s.Append("|"); 
        s.AppendFormat("{0},{1}", kvp.Key, kvp.Value); 
       } 
       return s.ToString(); 
      } 
      set{ 
       string[] aKvps = value.Split('|'); 
       Dct = new Dictionary<string,string>(); 
       for(int i=0; i<aKvps.Length; ++i){ 
        string aPair = aKvps[i].Split(','); 
        if (aPair.Length == 2) 
         Dct.Add(aPair[0], aPair[1]); 
       } 
      } 
    } 

} 

Я набрал это из памяти и не пытался его скомпилировать, так что может быть ошибка или два. Но, надеюсь, у него есть идея. Кроме того, это предполагает, что ваши данные не будут иметь запятую или трубку в ключах значений. Если это так, это решение может не сработать для вас.

0

Невозможно сериализовать словарь в dotnet. Мое решение заключается в следующем:

Выход:

**<Person> 
    <FirstName>John</FirstName> 
    <LastName>Doe</LastName> 
    <Attributes> 
    <PhoneNumber>12345</PhoneNumber> 
    <StreetName>StackOverFlow Street</StreetName> 
    <StreetNumber>51</StreetNumber> 
    </Attributes> 
</Person>** 

Основной код

public class Person 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public Dictionary<string, string> Attributes { get; set; } 
    } 

    public class DictionarySerializer 
    { 
     private StringBuilder _sBuilder; 
     private XmlWriterSettings _writerSettings; 
     private XmlWriter w; 

     public string WriteXml(Person personObject) 
     { 
      _sBuilder = new StringBuilder(); 
      _writerSettings = new XmlWriterSettings(); 

      _writerSettings.Indent = true; 
      _writerSettings.OmitXmlDeclaration = true; 
      w = XmlWriter.Create(_sBuilder, _writerSettings); 

      //if you remove person properties any dictionary can be turned into XML. 
      w.WriteStartElement("Person");   
      w.WriteElementString("FirstName", personObject.FirstName); 
      w.WriteElementString("LastName", personObject.LastName); 
      w.WriteStartElement("Attributes"); 

      foreach (var item in personObject.Attributes) 
      { 
       w.WriteElementString(item.Key, item.Value); 
      } 

      w.WriteEndElement(); 
      w.WriteEndElement(); 
      w.Close(); 

      return _sBuilder.ToString(); 
     } 
    } 

Использование кода

public partial class _Default : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      Person objP = new Person(); 
      objP.FirstName = "John"; 
      objP.LastName = "Doe"; 

      objP.Attributes = new Dictionary<string, string>(); 

      objP.Attributes.Add("PhoneNumber", "12345"); 
      objP.Attributes.Add("StreetName", "StackOverFlow Street"); 
      objP.Attributes.Add("StreetNumber", "51"); 

      DictionarySerializer ds = new DictionarySerializer(); 
      string val = ds.WriteXml(objP); 
     } 
    }