c#中的XML序列化和反序列化
序列化是一种将对象(如类的实例或对象集合)转换为字节流或字符流的机制,您可以将这些字节流或字符流保存到文件或数据库中,甚至可以通过Internet发送到其他系统。当需要时,您可以反序列化数据—将其转换回内存中一个可用的对象。. net框架包含许多类来帮助完成这个过程,并通过XmlSerializer类和System.Xml.Serialization库提供了对XML序列化(将对象序列化为XML数据文件)的内置支持。
本文简要概述了c#编程语言中的XML序列化和反序列化。它假定读者对c#和Microsoft Visual Studio有一定的了解,所以完全的初学者会从中受益探索c#编程的基本原理第一。不熟悉XML的读者应该这样做学习XML编程的基础知识在继续之前。如果打算使用序列化与其他系统交换数据尤其重要。
在C#中序列化XML
许多. net框架对象和类可以序列化,而不需要向代码中添加任何特殊的指令或属性。默认情况下,类的所有公共属性都是可序列化的。
下面的示例在Visual c#控制台应用程序中定义了一个简单的类,然后将内容序列化到控制台窗口。
/* * * Udemy.com * XML序列化和反序列化在c# * */使用系统;使用System.Xml.Serialization;命名空间XMLTest1 {public class Test {public String value1;公共字符串value2;}类程序{静态void main(String [] args){test mytest = new test(){value1 =“值1”,value2 =“值2”};XmlSerializer x = new XmlSerializer(myTest.GetType());x.serialize(控制台.out,mytest);Console.ReadKey ();}}}
实际序列化由类XMLSerializer的实例从System.xml.serialization命名空间完成。Serializer的构造函数需要参考它应该使用的对象类型 - 可以通过使用它来获得gettype()方法,或对该函数的调用类型()并将类名作为唯一的参数指定。
的连载()方法接受已定义类型的对象,将该对象转换为XML,然后将信息写入已定义的流(在本例中,是控制台输出流的TextWriter对象)。示例代码的XML输出如下所示:
< ?xml version = " 1.0 " encoding = " ibm850 " ?>Value 1 Value 2
XML输出中的元素和属性的名称由对象的属性和字段的名称设置。
您可以将序列化的输出定向到各种。net流,包括MemoryStream(使用XmlWriter和StringWriter)、FileStream和NetworkStream类。在XPathNavigator实例的帮助下,也可以将对象序列化到XmlDocument中,如下例所示:
/* * * Udemy.com * XML序列化和反序列化在c# * */使用系统;使用System.Xml;使用System.Xml.XPath;使用System.Xml.Serialization;命名空间XMLTest1 {public class Test {public String value1;公共字符串value2;}类程序{static void Main(string[] args) {XmlDocument myXml = new XmlDocument();XPathNavigator xNav = myXml.CreateNavigator();Test myTest = new Test() {value1 = "Value 1", value2 = "Value 2"};XmlSerializer x = new XmlSerializer(myTest.GetType()); using (var xs = xNav.AppendChild()) { x.Serialize(xs, myTest); } Console.WriteLine(myXml.OuterXml); Console.ReadKey(); } } }
反序列化XML数据
反序列化是采用XML格式数据并将其转换为.NET Framework对象的过程:上面显示的过程的反向。提供XML是形成良好的,准确地匹配目标类型的结构,反序列化是相对简单的任务。
在下面的例子中,前面例子的XML输出被硬编码到一个字符串中,但是它可以从网络流或外部文件中获取。类的实例来反序列化字符串测试类,然后该示例将字段打印到控制台。要获得可以传递到XmlSerializer的构造函数中的合适流,StringReader(来自系统。IO命名空间)。
/* * * Udemy.com * XML序列化和反序列化在c# * */使用系统;使用先;使用System.Xml.Serialization;命名空间XMLTest1 {public class Test {public String value1;公共字符串value2;} class Program {static void Main(string[] args) {string xData = "";XmlSerializer x = new XmlSerializer(typeof(Test));测试myTest = (Test)x。反序列化(新StringReader (xData)); Console.WriteLine("V1: " + myTest.value1); Console.WriteLine("V2: " + myTest.value2); Console.ReadKey(); } } } Value 1 Value 2
序列化列表和集合
您可以将数组,通用列表和其他集合对象序列化为XML,只要其类实现了ICollection或IEnumerable。
简单数组和泛型列表通常不需要修改,在最终输出中可能出现相同的结果。例如,是否将对象声明为数组测试对象或作为通用列表测试对象,XMLSerializer将使用相同的XML代码写入:
<?XML Version =“1.0”编码=“IBM850”?>a1 value1> b1 value2> test> b1 value1> b2 value2> test> Arrayoftest>
因此,这种格式的XML数据可以反序列化为测试对象或数组测试对象。编程器由编程器指定应使用哪种类型的对象用于反序列化。
使用属性控制序列化
在序列化数据以便与其他应用程序交换时,或者在处理预定义的XML模式时,能够更改过程中使用的元素和属性名是很有用的。默认情况下,XML输出中的元素是以它们所基于的属性或字段命名的。您可以使用XmlRoot属性重命名根节点,并通过使用XmlElement属性并设置它来更改子节点的名称ElementName。
可以为一个属性指定多个属性,方法是在括号内用逗号分隔它们。这通常采取的形式[attributename property1 = value1, property2 = value2…))
[XmlRoot("XTest")] public class Test {[XmlElement(ElementName="V1")] public String value1;[XmlElement(“V2”)]public String value2;}
注意,当您只指定元素名称时,可以省略属性名称。
添加XMLElement属性,如上所示,不仅设置要使用的名称,但它还告诉XMLSerializer为该字段使用XML元素。您可以将value1更改为属性XTest.使用XMLAttribute声明字段来表示元素。
数组和集合使用了两个不同的属性。XmlArray控制列表的根节点,和XmlArrayItem控制该数组中的每个元素。
[XmlRoot("XTest")] public class Test {[XmlElement(ElementName="V1")] public String value1;[XmlElement(ElementName="V2")] public String value2;[XmlArray("OtherValues")] [XmlArrayItem("OValue")] public List others = new List();}
上面的例子被序列化为XML,格式如下所示:
< ?xml version = " 1.0 " encoding = " ibm850 " ?>A1 B1 Test
在某些情况下,您可能希望从输出中排除公共属性或字段。这可以通过添加该属性来完成XmlIgnore到类声明中的属性:
[XmlIgnore] public String value2;…
最后,在处理已定义的模式时,通常需要删除由XmlSerializer添加的标准名称空间定义。调用连载()XmlSerializer实例的方法。此方法的一个可选参数指定要使用的名称空间、XmlSerializerNamespaces集合,并且可以包含空值。
XmlSerializer x = new XmlSerializer(myTest.GetType());XmlSerializerNamespaces ns = new XmlSerializerNamespaces();ns。添加(" "," ");x.Serialize(控制台。myTest, ns);
当然,也可以使用相同的XmlSerializerNamespaces集合来添加名称空间。但是,通常使用名称空间XMLOOT属性的属性与上面的代码相结合。
通过牢记或预先计划,在您的应用程序编写课程时使用的结构的序列化需求,可以将对象持久性和将外部数据文件加载到应用程序中,以非常少量的编程工作量。
重写类的序列化
如前所述,类的所有公共属性和类都会自动序列化,通常可以在不使用任何指令或属性的情况下将其转换为XML。默认情况下,私有属性和字段不会序列化。要包含这些,并且对于对对象序列化如何序列化为XML来说,可以更精确地控制,您可以覆盖整个序列化过程。
为此,您可以在类中实现IXmlSerializable,并包括XML序列化工作所需的三个方法:GetSchema()、WriteXml()和ReadXml()。
关于如何使用这些方法所使用的XmlWriter和XmlReader类的详细解释超出了本文的范围。在这样的级别上处理数据可能会利用c#编程的许多不同方面和. net框架的各种技术。要了解更高级的c#信息,c# 2012基础在Udemy.com形成了一个完整的课程,从初学者水平的项目到高级概念,并包含更多的例子的序列化第三部分。