C# 序列化与反序列化之xml对属性或者字段的子类化的子对象进行序列化的解决方案
xml序列化涉及到XmlRoot,XmlInclude,XmlElement,XmlAttribute,XmlType(用于继承的子类),XmlArray,XmlArrayItem(集合和集合项)等
新建控制台console项目,添加类XmlPerson以及XmlPerson的子类XmlStudent,XmlTeacher,添加Address类以及Address的的子类USAddress,AUAddress
1、运行的主方法代码如下:
using log4net; using System; using System.Data; using System.Data.SQLite; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.IO.MemoryMappedFiles; using System.IO.Pipes; using System.Linq; using System.Net; using System.Security.AccessControl; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; using System.Reflection; using System.ServiceModel; using System.ServiceModel.Channels; using System.Runtime.Serialization; namespace SupremeConsole { class Program { static void Main(string[] args) { TestSeri(); Console.ReadLine(); } public static void TestSeri() { //Team team = new Team { TName="123",PlayerList = { new Person { Name="1",Age=1},new Person { Name = "2", Age = 2 } } }; #region BinarySerialize 必须添可序列化属性,即要序列化的对象必须添加SerializableAttribute属性,[Serializable] //string s = SerializeManager.Instance.BinarySerialize<Team>(team);//序列化 //Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine("测试序列化成功。。。"); //Console.WriteLine($"测试序列化结果: {s}"); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "序列化11111.bin");//序列化 //SerializeManager.Instance.BinarySerialize<Team>(team, path); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "序列化11111.bin"); //Team test = SerializeManager.Instance.BinaryDeserialize<Team>(path);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} #endregion #region SoapSerialize 必须添可序列化属性,即要序列化的对象必须添加SerializableAttribute属性,[Serializable] //string s = SerializeManager.Instance.SoapSerialize<Team>(team);//序列化 //Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine("测试序列化成功。。。"); //Console.WriteLine($"测试序列化结果: {s}"); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Soap序列化.xml");//序列化 //SerializeManager.Instance.SoapSerialize<Team>(team, path); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Soap序列化.xml"); //Team test = SerializeManager.Instance.SoapDeserialize<Team>(path);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} #endregion #region XmlSerialize 要序列化的对象可以不添加SerializableAttribute属性,[Serializable] //XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12,Address="住址。。。。" }; XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new Address { Street = "默默大街三号", PostCode = "233664" } }; //XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new USAddress { Street = "默默大街三号", PostCode = "233664", Neighbor="邻居666" } }; string s = SerializeManager.Instance.XmlSerialize<XmlPerson>(xmlPerson);//序列化 Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("测试序列化成功。。。"); Console.WriteLine($"测试序列化结果: {s}"); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "序列化.txt");//序列化 //SerializeManager.Instance.XmlSerialize<TestClass>(testClass, path); //备用 //string json = "{"Address":"中国南京","Age":10,"Id":1,"Name":"张三","Sex":"男"}"; //TestClass test = SerializeManager.Instance.DataContractJsonDeserializeJson<TestClass>(json);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "序列化.txt"); //TestClass test = SerializeManager.Instance.XmlDeserialize<TestClass>(path);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} #endregion } } }
2、xml对属性或者字段的子类化的子对象进行序列化,首先添加类XmlPerson以及XmlPerson的子类XmlStudent,XmlTeacher,添加Address类以及Address的的子类USAddress,AUAddress
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Serialization; namespace SupremeConsole { #region 继承XmlPerson以及继承的子类 /// <summary> /// xml序列化测试类 /// </summary> //继承XmlPerson的子类XmlStudent,XmlTeacher的序列化 //[XmlInclude(typeof(继承的子类1))]//XmlInclude指明了,继承子类的序列化的类型,如 XmlInclude(typeof(XmlStudent)),或者再序列化的时候添加子类类型XmlSerializer xs = new XmlSerializer (typeof (XmlPerson),new Type[] { typeof (继承的子类1), typeof (继承的子类2)} );,如:new Type[] { typeof (XmlStudent), typeof (XmlTeacher)}; [XmlRoot("haha")] //[XmlInclude(typeof(XmlStudent))] //[XmlInclude(typeof(XmlTeacher))] public class XmlPerson { /// <summary> /// 姓名 /// </summary> [XmlElement("MyName", Order = 2)] public string Name { get; set; } /// <summary> /// 年龄 /// </summary> [XmlAttribute("MyAge")] public int Age { get; set; } ///// <summary> ///// 住址 ///// </summary> //[XmlElement("Residence", Order = 1)] //public string Address { get; set; } /// <summary> /// 住址 /// </summary> [XmlElement("Residence", Order = 1)] public Address HomeAddress = new Address();//常规序列化 } [XmlType("SubXmlPersonIsXmlStudent")]//XmlStudent序列化后的名称 public class XmlStudent : XmlPerson { /// <summary> /// 学号 /// </summary> public string StuNumber { get; set; } } [XmlType("SubXmlPersonIsXmlTeacher")]//XmlTeacher序列化后的名称 public class XmlTeacher : XmlPerson { /// <summary> /// 工号 /// </summary> public string TeachNumber { get; set; } } #endregion #region Address以及继承的子类 public class Address //常规序列化 { public string Street, PostCode; } [XmlType("USAddressISSubAddress")] public class USAddress : Address //子类的序列化 { public string Neighbor; //邻居 } [XmlType("AUAddressISSubAddress")] public class AUAddress : Address //子类的序列化 { public string OldNeighbor; //邻居 } #endregion }
运行效果:
测试序列化成功。。。 测试序列化结果: <?xml version="1.0"?> <haha xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" MyAge="12"> <Residence> <Street>默默大街三号</Street> <PostCode>233664</PostCode> </Residence> <MyName>1111</MyName> </haha>
运行结果中的红色标记就是XmlPerson中的HomeAddress 设置的别名Residence
/// <summary>
/// 住址
/// </summary>
[XmlElement("Residence", Order = 1)]
public Address HomeAddress = new Address();//常规序列化
修改XmlPerson中的
[XmlElement("Residence", Order = 1)]
public Address HomeAddress = new Address();//常规序列化
改成
[XmlElement("Residence", Order = 1)]
public Address HomeAddress = new USAddress();//子类的序列化
同时修改 Address,在Address类上添加特性[XmlInclude(typeof(USAddress))],[XmlInclude(typeof(AUAddress))]
[XmlInclude(typeof(USAddress))]
[XmlInclude(typeof(AUAddress))]
public class Address //常规序列化
{
public string Street, PostCode;
}
把TestSeri法中的
XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new Address { Street = "默默大街三号", PostCode = "233664" } };
改成
XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new USAddress { Street = "默默大街三号", PostCode = "233664", Neighbor="邻居666" } };
运行结果:
测试序列化成功。。。 测试序列化结果: <?xml version="1.0"?> <haha xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" MyAge="12"> <Residence xsi:type="USAddressISSubAddress"> <Street>默默大街三号</Street> <PostCode>233664</PostCode> <Neighbor>邻居666</Neighbor> </Residence> <MyName>1111</MyName> </haha>
运行的结果来看出现了 Residence xsi:type="USAddressISSubAddress",出现的原因是在Address类上添加特性[XmlInclude(typeof(USAddress))],这就是xml对属性或者字段的子类化的子对象进行序列化的结果
要想出现下面的效果
修改
[XmlElement("Residence", Order = 1)]
//public Address HomeAddress = new USAddress();//子类的序列化
改为
[XmlElement("Residence", typeof(Address), Order = 1)]
[XmlElement("USAddressISSubAddressResidence", typeof(USAddress), Order = 1)]
[XmlElement("AUAddressISSubAddressResidence", typeof(AUAddress), Order = 1)]
public Address HomeAddress = new USAddress();//子类的序列化
这时候就可以达到上述效果,但是Address类上添加特性[XmlInclude(typeof(USAddress))]对结果没有影响,可以去掉。
3、xml对属性或者字段是泛型集合的序列化处理方式如下
首先把XmlPerson类中的
public Address HomeAddress = new USAddress();//子类的序列化
改成
[XmlArray("集合列表的名称", Order = 1)]//默认序列化以后的名称是Addresses ,现在通过XmlArray来修改为指定的名称,如:[XmlArray("集合列表的名称", Order = 1)]
[XmlArrayItem("集合列表中的项的名称")]//默认序列化以后的名称是Address,现在通过XmlArrayItem来修改为指定的名称,如:[XmlArrayItem("集合列表中的项的名称")]
public List<Address> Addresses = new List<Address>();
注意:XmlElement、XmlText 和 XmlAnyElement 不能与 XmlAttribute、XmlAnyAttribute、XmlArray 或 XmlArrayItem 一起使用,否则会报错。
把TestSeri方法中的
XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new USAddress { Street = "默默大街三号", PostCode = "233664", Neighbor="邻居666" } };
改成
XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, Addresses = new List<Address> { new Address { Street = "大街三三号", PostCode = "123"}, new USAddress { Street = "大街六六号", PostCode = "456", Neighbor = "邻居666" } } };
运行效果
把 public List<Address> Addresses = new List<Address>();上的特性改成
[XmlElement("Address", typeof(Address), Order = 1)]
[XmlElement("AUAddress", typeof(AUAddress))]
[XmlElement("USAddress", typeof(USAddress))]
public List<Address> Addresses = new List<Address>();
把TestSeri方法中的
XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, Addresses = new List<Address> { new Address { Street = "大街三三号", PostCode = "123"}, new USAddress { Street = "大街六六号", PostCode = "456", Neighbor = "邻居666" } } };
改成
XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, Addresses = new List<Address> { new Address { Street = "大街三三号", PostCode = "123"}, new USAddress { Street = "大街六六号", PostCode = "456", Neighbor = "邻居666" }, new AUAddress { Street = "大街八八号", PostCode = "789", OldNeighbor = "旧朋友邻居8888" } } };
运行效果
把
[XmlElement("Address", typeof(Address), Order = 1)]
[XmlElement("AUAddress", typeof(AUAddress))]
[XmlElement("USAddress", typeof(USAddress))]
public List<Address> Addresses = new List<Address>();
上的特性
改成
[XmlArray(Order = 1)]
[XmlArrayItem("Address", typeof(Address))]
[XmlArrayItem("AUAddress", typeof(AUAddress))]
[XmlArrayItem("USAddress", typeof(USAddress))]
public List<Address> Addresses = new List<Address>();
运行效果
上述测试的全部代码如下:
Main主方法代码:
using log4net; using System; using System.Data; using System.Data.SQLite; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.IO.MemoryMappedFiles; using System.IO.Pipes; using System.Linq; using System.Net; using System.Security.AccessControl; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; using System.Reflection; using System.ServiceModel; using System.ServiceModel.Channels; using System.Runtime.Serialization; using System.Collections.Generic; namespace SupremeConsole { class Program { static void Main(string[] args) { TestSeri(); Console.ReadLine(); } public static void TestSeri() { //Team team = new Team { TName="123",PlayerList = { new Person { Name="1",Age=1},new Person { Name = "2", Age = 2 } } }; #region BinarySerialize 必须添可序列化属性,即要序列化的对象必须添加SerializableAttribute属性,[Serializable] //string s = SerializeManager.Instance.BinarySerialize<Team>(team);//序列化 //Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine("测试序列化成功。。。"); //Console.WriteLine($"测试序列化结果: {s}"); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "序列化11111.bin");//序列化 //SerializeManager.Instance.BinarySerialize<Team>(team, path); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "序列化11111.bin"); //Team test = SerializeManager.Instance.BinaryDeserialize<Team>(path);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} #endregion #region SoapSerialize 必须添可序列化属性,即要序列化的对象必须添加SerializableAttribute属性,[Serializable] //string s = SerializeManager.Instance.SoapSerialize<Team>(team);//序列化 //Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine("测试序列化成功。。。"); //Console.WriteLine($"测试序列化结果: {s}"); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Soap序列化.xml");//序列化 //SerializeManager.Instance.SoapSerialize<Team>(team, path); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Soap序列化.xml"); //Team test = SerializeManager.Instance.SoapDeserialize<Team>(path);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} #endregion #region XmlSerialize 要序列化的对象可以不添加SerializableAttribute属性,[Serializable] //XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12,Address="住址。。。。" }; //XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new Address { Street = "默默大街三号", PostCode = "233664" } }; //XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, HomeAddress = new USAddress { Street = "默默大街三号", PostCode = "233664", Neighbor="邻居666" } }; XmlPerson xmlPerson = new XmlPerson { Name = "1111", Age = 12, Addresses = new List<Address> { new Address { Street = "大街三三号", PostCode = "123"}, new USAddress { Street = "大街六六号", PostCode = "456", Neighbor = "邻居666" }, new AUAddress { Street = "大街八八号", PostCode = "789", OldNeighbor = "旧朋友邻居8888" } } }; string s = SerializeManager.Instance.XmlSerialize<XmlPerson>(xmlPerson);//序列化 Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("测试序列化成功。。。"); Console.WriteLine($"测试序列化结果: {s}"); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Addresses序列化.txt");//序列化 //SerializeManager.Instance.XmlSerialize<XmlPerson>(xmlPerson, path); //string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Addresses序列化.txt"); //XmlPerson test = SerializeManager.Instance.XmlDeserialize<XmlPerson>(path);//反序列化 //if (test != null) //{ // Console.WriteLine($"测试序列化结果:{test.ToString()}"); //} #endregion } } }
xmlPerson类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Serialization; namespace SupremeConsole { #region 继承XmlPerson以及继承的子类 /// <summary> /// xml序列化测试类 /// </summary> //继承XmlPerson的子类XmlStudent,XmlTeacher的序列化 //[XmlInclude(typeof(继承的子类1))]//XmlInclude指明了,继承子类的序列化的类型,如 XmlInclude(typeof(XmlStudent)),或者再序列化的时候添加子类类型XmlSerializer xs = new XmlSerializer (typeof (XmlPerson),new Type[] { typeof (继承的子类1), typeof (继承的子类2)} );,如:new Type[] { typeof (XmlStudent), typeof (XmlTeacher)}; [XmlRoot("haha")] //[XmlInclude(typeof(XmlStudent))] //[XmlInclude(typeof(XmlTeacher))] public class XmlPerson { /// <summary> /// 姓名 /// </summary> [XmlElement("MyName", Order = 2)] public string Name { get; set; } /// <summary> /// 年龄 /// </summary> [XmlAttribute("MyAge")] public int Age { get; set; } ///// <summary> ///// 住址 ///// </summary> //[XmlElement("Residence", Order = 1)] //public string Address { get; set; } ///// <summary> ///// 住址 ///// </summary> //[XmlElement("Residence", Order = 1)] //public Address HomeAddress = new Address();//常规序列化 ///// <summary> ///// 住址 ///// </summary> //[XmlElement("Residence", Order = 1)] //public Address HomeAddress = new USAddress();//子类的序列化 ///// <summary> ///// 住址 ///// </summary> //[XmlElement("Residence", typeof(Address), Order = 1)] //[XmlElement("USAddressISSubAddressResidence", typeof(USAddress), Order = 1)] //[XmlElement("AUAddressISSubAddressResidence", typeof(AUAddress), Order = 1)] //public Address HomeAddress = new USAddress();//子类的序列化 ///// <summary> ///// 地址集合 ///// </summary> //[XmlArray("集合列表的名称", Order = 1)] //[XmlArrayItem("集合列表中的项的名称")] //public List<Address> Addresses = new List<Address>(); [XmlArray(Order = 1)] [XmlArrayItem("Address", typeof(Address))] [XmlArrayItem("AUAddress", typeof(AUAddress))] [XmlArrayItem("USAddress", typeof(USAddress))] public List<Address> Addresses = new List<Address>(); //[XmlElement("Address", typeof(Address), Order = 1)] //[XmlElement("AUAddress", typeof(AUAddress))] //[XmlElement("USAddress", typeof(USAddress))] //public List<Address> Addresses = new List<Address>(); } [XmlType("SubXmlPersonIsXmlStudent")]//XmlStudent序列化后的名称 public class XmlStudent : XmlPerson { /// <summary> /// 学号 /// </summary> public string StuNumber { get; set; } } [XmlType("SubXmlPersonIsXmlTeacher")]//XmlTeacher序列化后的名称 public class XmlTeacher : XmlPerson { /// <summary> /// 工号 /// </summary> public string TeachNumber { get; set; } } #endregion #region Address以及继承的子类 [XmlInclude(typeof(USAddress))] [XmlInclude(typeof(AUAddress))] public class Address //常规序列化 { public string Street, PostCode; } [XmlType("USAddressISSubAddress")] public class USAddress : Address //子类的序列化 { public string Neighbor; //邻居 } [XmlType("AUAddressISSubAddress")] public class AUAddress : Address //子类的序列化 { public string OldNeighbor; //邻居 } #endregion }