类序列化到XML

时间:2013-12-19 12:03:19

标签: c# xml serialization xml-serialization

鉴于以下课程设计:

 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。

4 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

您可以使用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;
}

.ToString()上调用XElement应该会为您提供xml格式的字符串。

答案 2 :(得分:0)

这里有两个选择XmlSerializer(它不能用于Dictionary或List类型的反序列化),或者你可以使用在.net 3.0中添加的DataContractSerializer,这里有很多优点:形成这个post

  • 针对速度进行了优化(通常比XmlSerializer快10%左右)

  • “选择加入”中的
  • - 只有您专门标记为[DataMember]的内容才会被序列化

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

注意:您应该添加对C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ 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;
    }
    }

答案 3 :(得分:0)

完整的工作解决方案

数据模型

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