类的序列化到XML

问题描述:

考虑下面的类设计:类的序列化到XML

public class AllUserCollections 
    { 
     public List<UserCollection> UserCollections { get; set; } 

     public AllUserCollections() 
     { 
      this.UserCollections = new List<UserCollection>(); 
     } 
    } 

    public class UserCollection 
    { 
     public string UserGroup { get; set; } 
     public Dictionary<int,User> Users { get; set; } 

     public UserCollection(string userGroup) 
     { 
      this.UserGroup = userGroup; 
      this.Users = new Dictionary<int, User>(); 
     } 
    } 

    public class User 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public string Location { get; set; } 
     public AgeGroup UserAgeGroup { get; set; } 
    } 

    public enum AgeGroup 
    { 
     Twenties, 
     Thirties, 
     Fourties, 
    } 

如何使用我的现有串行化类我序列这XML?

public static class HardDriveService 
    { 
     private static string docsFolderPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); 
     private const string fileName = "AllUserCollections.xml"; 
     private static string filePath = Path.Combine(docsFolderPath, fileName); 

     private static bool FileExists(string fullFilePath) 
     { 
      if (File.Exists (fullFilePath)) 
       return true; 

      return false; 
     } 

     public static void Save(AllUserCollections allUserCollections) 
     { 
      if (FileExists(filePath)) 
      { 
       File.Delete (filePath); 
      } 

      XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType()); 
      using(StreamWriter writer = new StreamWriter(filePath)) 
      { 
       serializer.Serialize(writer.BaseStream, allUserCollections); 
      } 
     } 

     public static AllUserCollections Read() 
     { 
      AllUserCollections allUserCollections = new AllUserCollections(); 
      XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType()); 

      if (FileExists(filePath)) 
      { 
       StreamReader reader = new StreamReader(filePath); 
       object deserialized = serializer.Deserialize(reader.BaseStream); 
       allUserCollections = (AllUserCollections)deserialized; 
      } 

      return allUserCollections; 
     } 


    }//End of class. 

问题

我的代码似乎不能在这条线 -

XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType()); 

我不知道它是否与类需要被明确标记为“可序列化”呢?我将如何做到这一点?

用法 此代码将运行在iphone上,并直接从应用程序保存/读取到iPhone上的XML硬盘。

+1

你想达到什么您已经阅读文档试图 –

+1

请开始什么:http://msdn.microsoft.com/en-us/library/ms233843.aspx – Samuel

+0

是WCF或者只是序列化文件 –

在这里,你有两个选择的XmlSerializer(它不会与字典或列表类型反序列化工作),或者你可以使用的DataContractSerializer这在.NET 3.0中加入,在这里有很多的优点是少数:形成这种post

  • 优化速度(比XmlSerializer的快约10%,典型地)

  • 在“选入” - 仅东西,你特别标记为[数据成员]将被序列

  • 不支持XML属性(速度的原因)

注意:你应该添加参照C:\ Program Files文件(x86)的\参考大会\微软\ Framework.NETFramework \ V4.0 \ System.Runtime.Serialization.dll

//to serialize 
     SerializeHelper.Serialize("your filename" ,new AllUserCollections()); 
// deserialize 
     var usertCollections = SerializeHelper.Deserialize<AllUserCollections>("yourfile name"); 


//code 
[DataContract] 
    public class AllUserCollections 
    { 
     public List<UserCollection> UserCollections { get; set; } 

     public AllUserCollections() 
     { 
      this.UserCollections = new List<UserCollection>(); 
     } 
    } 
    [DataContract()] 
    public class UserCollection 
    { 
     [DataMember] 
     public string UserGroup { get; set; } 

     [DataMember] 
     public Dictionary<int, User> Users { get; set; } 

     public UserCollection(string userGroup) 
     { 
      this.UserGroup = userGroup; 
      this.Users = new Dictionary<int, User>(); 
     } 
    } 
    [DataContract()] 
    public class User 
    { [DataMember] 
     public int ID { get; set; } 
     [DataMember] 
     public string Name { get; set; } 
     [DataMember] 
     public string Location { get; set; } 
     [DataMember] 
     public AgeGroup UserAgeGroup { get; set; } 
    } 
    [DataContract] 
    public enum AgeGroup 
    { 
     Twenties, 
     Thirties, 
     Fourties, 
    } 
    public static class SerializeHelper 
    { 
     public static void Serialize<T>(string fileName, T obj) 
    { 
     using (FileStream writer = new FileStream(fileName, FileMode.Create)) 
     { 
     DataContractSerializer ser = 
      new DataContractSerializer(typeof(T)); 
     ser.WriteObject(writer, obj); 
     writer.Close(); 
     } 


    } 

    public static T Deserialize<T>(string fileName) 
    { 
     T des; 
     using (FileStream fs = new FileStream(fileName,FileMode.Open)) 
     { 
     XmlDictionaryReader reader = 
      XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()); 
     DataContractSerializer ser = new DataContractSerializer(typeof(T)); 
     des = 
      (T)ser.ReadObject(reader, true); 
     reader.Close(); 
     fs.Close(); 

     } 

     return des; 
    } 
    } 
+0

什么是DataContractSerializer? – Goober

+0

-1无“使用”块。 –

+0

@JohnSaunders我太忙了,并且已经快速发布了答案 –

你可以使用XElement建立一个XML格式。你可以使用它们大致如下:

public static XElement ToXml(this User user) 
{ 
    if (user == null) 
    { 
     throw new ArgumentException("User can not be null."); 
    } 

    XElement userElement = new XElement("User"); 
    userElement.Add(new XElement("ID", user.ID)); 
    userElement.Add(new XElement("Name", user.Name)); 
    userElement.Add(new XElement("Location", user.Location)); 
    userElement.Add(new XElement("UserAgeGroup", user.UserAgeGroup)); 

    return userElement; 
} 

public static string ToXml(this UserCollection userCollection) 
{ 
    if (userCollection == null) 
    { 
     throw new ArgumentException("UserCollection can not be null."); 
    } 

    XElement userCollectionElement = new XElement("UserCollection"); 
    userCollectionElement.Add(new XElement("UserGroup", userCollection.UserGroup)); 
    userCollectionElement.Add(new XElement("Users", 
              userCollection.Users.Select(x => new XElement("User", x.ToXml())); 

    return userCollectionElement; 
} 

调用上XElement.ToString()应该给你一个XML格式的字符串。

XMLSerializer不支持开箱即用的字典。你的UserCollection类有一个Dictionary。请参阅此链接以获取解决方法。 Why doesn't XmlSerializer support Dictionary?

除此之外,XMLSerializer要求您的类具有默认构造函数(UserCollection和User不),并且每个类都必须具有[Serializable]属性。

FULL工作溶液

数据模型

using System; 
using System.Collections.Generic; 

namespace iPhoneHardDriveCRUDPrototype 
{ 
    [Serializable] 
    public class AllUserCollections 
    { 
     public List<UserCollection> UserCollections { get; set; } 

     public AllUserCollections() 
     { 
      this.UserCollections = new List<UserCollection>(); 
     } 
    } 

    [Serializable] 
    public class UserCollection 
    { 
     public string UserGroup { get; set; } 
     public SerializableDictionary<int,User> Users { get; set; } 

     public UserCollection() 
     { 
      this.Users = new SerializableDictionary<int, User>(); 
     } 

     public UserCollection(string userGroup) 
     { 
      this.UserGroup = userGroup; 
      this.Users = new SerializableDictionary<int, User>(); 
     } 
    } 

    [Serializable] 
    public class User 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public string Location { get; set; } 
     public AgeGroup UserAgeGroup { get; set; } 

     public User() 
     { 

     } 
    } 

    [Serializable] 
    public enum AgeGroup 
    { 
     Twenties, 
     Thirties, 
     Fourties, 
    } 
} 

序列化字典

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

namespace iPhoneHardDriveCRUDPrototype 
{ 
    [XmlRoot("dictionary")] 
    public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable 
    { 
     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(); 
      } 
     } 



    }//End of Class.... 
} 

串行

using System; 
using System.IO; 
using System.Xml.Serialization; 
using System.Reflection; 
using System.Collections.Generic; 

namespace iPhoneHardDriveCRUDPrototype 
{ 
    public static class HardDriveService 
    { 
     private static string docsFolderPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); 
     private const string fileName = "AllUserCollections.xml"; 
     private static string filePath = Path.Combine(docsFolderPath, fileName); 

     private static bool FileExists(string fullFilePath) 
     { 
      if (File.Exists (fullFilePath)) 
       return true; 

      return false; 
     } 

     public static void Save(AllUserCollections allUserCollections) 
     { 
      if (FileExists(filePath)) 
      { 
       File.Delete (filePath); 
      } 

      XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType()); 
      using(StreamWriter writer = new StreamWriter(filePath)) 
      { 
       serializer.Serialize(writer.BaseStream, allUserCollections); 
      } 
     } 

     public static AllUserCollections Read() 
     { 
      AllUserCollections allUserCollections = new AllUserCollections(); 
      XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType()); 

      if (FileExists(filePath)) 
      { 
       StreamReader reader = new StreamReader(filePath); 
       object deserialized = serializer.Deserialize(reader.BaseStream); 
       allUserCollections = (AllUserCollections)deserialized; 
      } 

      return allUserCollections; 
     } 


    }//End of class. 
} 
+0

不,它不是一个完整的工作解决方案,因为您不能反序列化字典和列表类型我的解决方案使用datacontractserializer将更好地工作 –

+0

MonoTouch不支持DataContractSerializer。是的,我发布的可序列化字典类可以工作。 – Goober

+0

首先你还没有添加moonotouch标签第二个DataContractSerializer在Monotouch中被支持 –