业务实体对象(
Business Entity Object
)的序列化
Written by: Rickie Lee
Dec. 12, 2004
在分布式应用系统中,层与层之间的数据,如业务实体对象、
DataSet
、
Typed DataSet
等等,传递需要将对象序列化。其中
.Net Framework
内置支持
DataSet, Typed DataSet
对象的序列化。这里要讨论的是自定义业务实体对象(
Business Entity Object
)的序列化。
1.
使用
XmlSerializer
序列化自定义实体对象
将对象序列化到
XML
文档中和从
XML
文档中反序列化对象。
XML
序列化是将对象的公共属性和字段转换为序列格式(这里是指
XML
)以便存储或传输的过程。反序列化则是从
XML
输出中重新创建原始状态的对象。因此,可以将序列化视为将对象的状态保存到流或缓冲区的方法。
若要序列化对象,请调用
Serialize
方法。若要反序列化对象,请调用
Deserialize
方法。
以下代码示例显示了如何使用
XmlSerializer
类将
EmployeeEntity
对象序列化为
XML
格式:
using System.Xml.Serialization;
//
用于
XmlSerializer
类
//
创建一个
XmlSerializer
对象,用于序列化
EmployeeEntity
类型的对象
XmlSerializer serializer = new XmlSerializer(typeof(EmployeeEntity));
//
将
EmployeeEntity
对象序列化为名为“
MyXmlEmployeeEntity.xml”
的
XML
文件
TextWriter writer = new StreamWriter("MyXmlEmployeeEntity.xml");
serializer.Serialize(writer, employee);
writer.Close();
StreamReader sr = new StreamReader("MyXmlEmployeeEntity.xml");
txtResults.Text = sr.ReadToEnd();
sr.Close();
输出结果:
<?xml version="1.0" encoding="utf-8"?>
<EmployeeEntity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EmployeeNumber>1234</EmployeeNumber>
<EmploymentStatus>Active</EmploymentStatus>
<Nickname>Rickie</Nickname>
<LastName>Lee</LastName>
<FirstName>Rickie</FirstName>
<InputDateTime>2004-12-08T15:31:17.0674832-08:00</InputDateTime>
</EmployeeEntity>
2.
使用
SoapFormatter
类将自定义实体对象序列化为
SOAP
格式
以
SOAP
格式将对象或整个连接对象的图形序列化和反序列化。当使用
SOAP
协议向或从
XML Web services
传递对象,或者当使用
HTTP
远程通道向或从
Remoting
服务器传递对象时,也会发生
SOAP
序列化(隐式)。此外,也可以在使用
TCP
远程通道时指定
SOAP
格式化。
using System.Runtime.Serialization.Formatters.Soap; //
用于
SoapFormatter
类
...
//
创建
SoapFormatter
对象,用于序列化
EmployeeEntity
类型的对象
SoapFormatter formatter = new SoapFormatter();
//
将
EmployeeEntity
对象序列化为名为“
MySoapEmployeeEntity.xml”
的
SOAP (XML)
文件
FileStream stream = File.Create("MySoapEmployeeEntity.xml");
formatter.Serialize(stream, employee);
stream.Close();
StreamReader sr = new StreamReader("MySoapEmployeeEntity.xml");
txtResults.Text = sr.ReadToEnd();
sr.Close();
要对自定义实体组件使用
SOAP
序列化,必须使用
Serializable
属性注释您的实体类,如以下代码所示:
[Serializable]
public class EmployeeEntity
{
//
成员
}
输出结果(与
XmlSerializer
输出结果不一致):
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:EmployeeEntity id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/BusinessEntitySerialize/BusinessEntitySerialize%2C%20Version%3D1.0.1803.28706%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<employeeNumber id="ref-3">1234</employeeNumber>
<employmentStatus id="ref-4">Active</employmentStatus>
<nickname id="ref-5">Rickie</nickname>
<lastName id="ref-6">Lee</lastName>
<firstName href="#ref-5"/>
<inputDateTime>2004-12-08T15:56:55.1688704-08:00</inputDateTime>
</a1:EmployeeEntity>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
如果要自定义序列化过程中生成的
SOAP
格式,实体类必须实现
ISerializable
接口。您必须提供一个
GetObjectData
方法供
SoapFormatter
在序列化过程中调用,并提供一个特殊构造函数供
SoapFormatter
在还原序列化过程中调用以重新创建对象。以下代码显示了
ISerializable
接口、
GetObjectData
方法和特殊构造函数的使用:
using System.Runtime.Serialization; //
用于
ISerializable
接口以及相关类型
...
[Serializable]
public class OrderEntity : ISerializable
{
//
序列化函数,由
SoapFormatter
在序列化过程中调用
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext
ctxt)
{
//
向
SerializationInfo
对象中添加每个字段
info.AddValue("E
mployeeNumber
",
employeeNumber
);
//
必要时使用更多代码
...
}
//
还原序列化构造函数,由
SoapFormatter
在还原序列化过程中调用
public EmployeeEntity(SerializationInfo info, StreamingContext ctxt)
{
//
从
SerializationInfo
对象中还原序列化出各个
EmployeeEntity
字段
employeeNumber
= (string)info.GetValue("E
mployeeNumber
", typeof(string));
//
必要时使用更多代码
...
}
//
其他成员,同前
...
}
3.
将业务实体组件序列化为二进制格式
BinaryFormatter
以二进制格式将对象或整个连接对象图形序列化和反序列化。
要对自定义实体对象使用二进制序列化,必须使用
Serializable
属性注释您的自定义实体类。要自定义序列化过程中生成的二进制格式,自定义实体类必须实现
ISerializable
接口。这两种方案中的详细代码与
SOAP
序列化的代码相同。
以下代码示例显示了如何使用
BinaryFormatter
类将
EmployeeEntity
对象序列化为二进制格式。当使用
TCP
远程通道向或从
Remoting
服务器传递对象时,也会发生二进制序列化(隐式)。此外,为提高性能,您也可以在使用
HTTP
远程通道时指定二进制格式化。
using System.Runtime.Serialization.Formatters.Binary; //
用于
BinaryFormatter
类
...
//
创建
BinaryFormatter
对象,用于序列化
EmployeeEntity
类型的对象
BinaryFormatter formatter = new BinaryFormatter();
//
将
EmployeeEntity
对象序列化为名为“
MyBinaryEmployeeEntity.dat”
的二进制文件
FileStream stream = File.Create("MyBinaryEmployeeEntity.dat");
formatter.Serialize(stream, employee);
stream.Close();
4. Appendix & Source Code
(1) EmployeeEntity
自定义业务实体的
Source Code
[Serializable]
public class EmployeeEntity
{
#region Private Member
private string employeeNumber;
private string employmentStatus;
private string nickname;
private string lastName;
private string firstName;
private DateTime inputDateTime;
#endregion
#region Public Accessor
public string EmployeeNumber
{
get { return employeeNumber; }
set { employeeNumber = value; }
}
public string EmploymentStatus
{
get { return employmentStatus; }
set { employmentStatus = value; }
}
public string Nickname
{
get { return nickname; }
set { nickname = value; }
}
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
public DateTime InputDateTime
{
get { return inputDateTime; }
set { inputDateTime = value; }
}
#endregion
#region Supplement methods
public string Fullname
{
get { return firstName + " " + lastName; }
}
#endregion
public EmployeeEntity()
{
//
// TODO: Add constructor logic here
//
}
(2)
演示界面(
Visual Studio 2005 + .Net Framework 2.0
):
***
Any questions or error, please leave comments below. Thanks.
References:
1. Angela Crocker
、
Andy Olsen
和
Edward Jezierski, Microsoft,
设计数据层组件并在层间传递数据
, http://www.microsoft.com/china/msdn/archives/library/dnbda/html/BOAGag.asp
2. MSDN
当然我们的C#有一个处理这种烂设计的语法,就是接口的重新映射。这允许子类强行再声明一个属于自己的GetObjectData。但是一个合格的设计者要考虑VB,J#和JScript的用户。