您的位置:首页 > 编程语言 > C#

XML Serialization Using C#

2010-12-28 17:36 281 查看
Source URL:http://www.dotnetjohn.com/articles.aspx?articleid=173

XML Serialization Using C#...

Object serialization is a process through which an object's state is transformed into some serial data
format, such as XML or a binary format.

By: Nitin Pande



Date: December 5, 2004






Printer Friendly Version

Object Serialization is a process through which an object's state is transformed into some serial data format,
such as XML or a binary format. For example, you can serialize an object and transport it over the Internet
using HTTP between a client and a server. On the other end, deserialization reconstructs the object from the
stream. XML was designed to be a technology for data exchange across heterogeneous systems. It can be easily
transmitted between distributed components because of its platform independence and its simple, text-based,
self-describing format. In this article I will discuss the serialization of custom business objects to XML and
reconstruction the object back from the XML string, using C#. This process is called XML serialization and is
very well supported by .Net.

Some good uses for serialization/deserialization include:

Storing user preferences in an object.

Maintaining security information across pages and applications.

Modification of XML documents without using the DOM.

Passing an object from one application to another.

Passing an object from one domain to another.

Passing an object through a firewall as an XML string.

These are only a few of the many possibilities that serialization opens up for us.

Suppose we have an object defined and instantiated as shown below:

class
Person

{
private
String
personName;
private
Int32
personAge;

public
String
Name
{
get

{
return
personName;
}
set

{
personName = value
;
}
}

public
Int32
Age
{
get

{
return
personAge;
}
set

{
personAge = value
;
}
}
}

Listing 1: Demo class having public properties

Instantiation of the class is shown below:

Person oPerson = new
Person();
oPerson.Name = "Anthony"
;
oPerson.Age = 38;

Let's say that for some reason, we wanted to save a copy of this object just as it is at this very moment. We
could serialize it as an XML document that would look something like this:

<Person
>

<Name
>Anthony</Name
>

<Age
>38</Age
>

</Person
>


Then, at some later time when we needed to use the object again, we could just deserialize it and have our
object restored to us just as it was at the moment we serialized it.

However XML serialization follows certain rules and the classes defined by us have to conform to these rules.

XML serialization serializes only the public fields and property values of an object into an XML stream.

XML serialization does not include type information.

XML serialization requires a default constructor to be declared in the class that is to be serialized.

XML serialization requires all properties that are to be serialized
as read write properties. Read only properties are not serialized.

Serialize class

The .Net framework provides a rich collection of classes for serialization. As we are concerned with XML
serialization, we will examine the use of the XmlSerializer class. This is the central class for XML
serialization and its most important methods are the Serialize and Deserialize methods. Most of the articles
discussing XML serialization use IO streams for saving serialized data into XML files, however in my example
I will demonstrate the use of XML serialization to convert an object into XML string and store it in a memory
stream instead of an XML file. This technique is extremely useful in cases where a complex object is to be
converted to XML string and its properties have to be manipulated and then the object recreated from the XML
string on the fly!!

Attributes

Before we start with the process of demonstrating the technique of XML serialization let us have a small
discussion on Metadata Attributes. A complete discussion of Metadata Attributes is beyond the scope of this
article. Nevertheless we need to understand the concepts behind metadata attributes to understand how XML
serialization works. Attributes are annotations to an interface or a class definition to specify certain
behavior. Assemblies, classes, fields and methods, each can have attributes. Some are used by the compiler,
some are used by the runtime, e.g. to identify a method requires a call to a web service, or how to serialize a
class to XML. There is very little overhead associated when using attributes. Attaching attributes to a class
is done directly in the source code. The syntax to initialize a metadata attribute and attach it to a class or
a method in C# is either:

[Attribute(constructor-parameters-list )]

or:

[Attribute(constructor-parameters-list, property=value, … )]

The System.Xml.Serialization namespace introduces a set of attributes to control how classes are mapped to XML.
Let's look at a quick example: One of the attributes used with XML serialization is the XmlRootAttribute to
change the name of the root element of a serialization hierarchy. You would add the XmlRootAttribute to a class
like this:

using System.Xml.Serialization;

[XmlRootAttribute(Name="Human", IsNullable=false)]

public class Person

{

// class implementation goes here

}

If we make this change in the class declaration of listing 1, and serialize the instance of this class we will
get the XML generated resembling the one shown below:

<Human>

<Name>Anthony</Name>

<Age>38</Age>

</Human>

We would be using UTF-8 encoding for the creating the XML stream for the custom object as it supports a wide
range of Unicode character values and surrogates. For this purpose, we will make use of the UTF8Encoding class
provided by the .Net framework. For more information on UTF8Encoding you may want to refer to MSDN at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemtextutf8encodingclasstopic.asp
For explaining the concept of XML serialization I will create and use a demo class Animal with a number of
properties that describe an animal such as name, length, weight, place of existence etc. First create a C#
console application using the Visual Studio.Net and name the project as MySerializer
. This will automatically
create a namespace MySerializer. Import the following namespaces into the project:

System.Xml.Serialization

System.IO

System.Text

Now add a new class and name it Animal. The code for this class is given below:

using
System;
namespace
MySerializer
{
///

<summary>

///
Base class for the animal object hierarchy

///

</summary>

[XmlRootAttribute(ElementName="WildAnimal"
, IsNullable=false
)]
public
class
Animal

{
public
Animal()
{
//default constructor

}

private
String
animalName;
private
String
foodTypeCategory;
private
Boolean
isDomesticed;
private
String
placeOfExistence;
private
Int32
length;
private
Int32
height;
private
Int32
weight;

public
String
AnimalName
{
get

{
return
animalName;
}
set

{
animalName = value
;
}
}

public
String
FoodTypeCategory
{
get

{
return
foodTypeCategory;
}
set

{
foodTypeCategory = value
;
}
}
public
Boolean
IsDomesticed
{
get

{
return
isDomesticed;
}
set

{
isDomesticed = value
;
}
}

public
String
PlaceOfExistence
{
get

{
return
placeOfExistence;
}
set

{
placeOfExistence = value
;
}
}

public
Int32
Length
{
get

{
return
length;
}
set

{
length = value
;
}
}

public
Int32
Height
{
get

{
return
height;
}
set

{
height = value
;
}
}

public
Int32
Weight
{
get

{
return
weight;
}
set

{
weight = value
;
}
}
}
}

Listing 2: Custom class whose objects are to be serialized to XML

When you create the C# console application a default class by the name of Class1 gets added to the project. This
class contains the definition of the Main function that is the entry point of the assembly. Rename this class
from “Class1” to clsMain. In this class clsMain, we will define the custom methods to serialize and deserialize
the object of the class Animal. Apart from these there are helper methods to convert a UTF-8 byte array to
string and vice – versa.

The definition of these methods is given below:

///

<summary>

///
To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.

///

</summary>

///

<param name="characters">
Unicode Byte Array to be converted to String
</param>

///

<returns>
String converted from Unicode Byte Array
</returns>

private
String
UTF8ByteArrayToString ( Byte
[ ] characters )
{
UTF8Encoding encoding = new
UTF8Encoding ( );
String
constructedString = encoding.GetString ( characters );
return
( constructedString );
}

///

<summary>

///
Converts the String to UTF8 Byte array and is used in De serialization

///

</summary>

///

<param name="pXmlString"></param>

///

<returns></returns>

private
Byte
[ ] StringToUTF8ByteArray ( String
pXmlString )
{
UTF8Encoding encoding = new
UTF8Encoding ( );
Byte
[ ] byteArray = encoding.GetBytes ( pXmlString );
return
byteArray;
}

Listing 3: Helper Methods

Serialization

Now we will add a custom method SerializeObject
to the class clsMain
which will use the XmlSerializer to
serialize the object to XML string. The code for this method is given below:

///

<summary>

///
Method to convert a custom Object to XML string

///

</summary>

///

<param name="pObject">
Object that is to be serialized to XML
</param>

///

<returns>
XML string
</returns>

public
String
SerializeObject ( Object
pObject )
{
try

{
String
XmlizedString = null
;
MemoryStream memoryStream = new
MemoryStream ( );
XmlSerializer xs = new
XmlSerializer ( typeof
( Animal ) );
XmlTextWriter xmlTextWriter = new
XmlTextWriter ( memoryStream, Encoding.UTF8 );

xs.Serialize ( xmlTextWriter, pObject );
memoryStream = ( MemoryStream ) xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString ( memoryStream.ToArray ( ) );
return
XmlizedString;
}
catch
( Exception
e )
{
System.Console
.WriteLine ( e );
return
null
;
}
}

Listing 4: Method to serialize the custom business object

Let us look through the code carefully. First we create an instance of the MemoryStream
class since we intend
to keep the XML string in memory instead of saving it to a file. Instantiate the XmlSerializer
class with the
type of the class that is to be serialized. In our case this is the class Animal. Now we use the XmlTextWriter

Class that provides a fast, non-cached, forward-only way of generating streams or files containing XML data.
Notice that we use an overloaded constructor of the XmlTextWriter class and set the encoding to UTF-8. This
means that the XML document will be created with UTF-8 encoding. Now, we go to the most important step and that
is calling one of the overloaded implementations of the Serialize
method of the XmlSerializer object. We now
read the XML stream generated by the serializer from the BaseStream
of the XmlTextWriter
. Since the BaseStream
property returned by the XmlTextWriter is of the type System.IO.Stream, we can easily type cast it into
MemoryStream (which is derived from System.IO.Stream) for our purpose.

We now pass the Byte[] array returned by the ToArray() method of the MemoryStream object to the helper function
UTF8ByteArrayToString
. This method constructs the XML string from the binary array and returns the same. This
small piece of trick is performed by the overloaded implementation of the GetString() method of the UTF8Encoding

class. The output that is generated is given below:

<?xml version="1.0" encoding="utf-8"?>

<WildAnimal xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<AnimalName>Lion</AnimalName>

<FoodTypeCategory>Carnivore</FoodTypeCategory>

<IsDomesticed>false</IsDomesticed>

<PlaceOfExistence>Africa</PlaceOfExistence>

<Length>15</Length>

<Height>4</Height>

<Weight>900</Weight>

</WildAnimal>

Notice that all the properties defined in the class Animal are serialized into nodes and the name of the root
also gets changed from Animal to WildAnimal, this is because we had included the attribute XmlRootAttribute
in
the declaration of the class Animal.

Deserialization

Just as we had created a custom method to serialize the object, we will create another method in the class
clsMain
which will use the Deserialize() method of the XmlSerializer class to recreate the object from the XML
string. The code for this method is given below:

///

<summary>

///
Method to reconstruct an Object from XML string

///

</summary>

///

<param name="pXmlizedString"></param>

///

<returns></returns>

public
Object
DeserializeObject ( String
pXmlizedString )
{
XmlSerializer xs = new
XmlSerializer ( typeof
( Automobile ) );
MemoryStream memoryStream = new
MemoryStream ( StringToUTF8ByteArray ( pXmlizedString ) );
XmlTextWriter xmlTextWriter = new
XmlTextWriter ( memoryStream, Encoding.UTF8 );

return
xs.Deserialize ( memoryStream );
}

To get the Animal object back from the XML string you will simply call this method and pass the XML string. It
will first convert the XML string to a byte array (exactly the reverse of what we did in serialization) and
then recreate the object from the XmlSerializer.

There you are!! You have now learnt the entire process of serializing a custom object into an XML string and
keeping it in an in memory variable and then reconstructing it back using deserialization. With the help of
powerful XMLDocument class and other rich XML parsing classes and readers (such as XmlReader) provided by .Net
you can change values or nodes , change attributes and apply advanced XML processing functions to XML document.

Happy Programming!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: