业务实体对象(Business Entity Object)的序列化

业务实体对象( 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
 
posted on 2004-12-13 09:00 Rickie 阅读(2388) 评论(5)   编辑  收藏 引用 网摘 所属分类: 8.架构及模式
<script type=text/javascript> // </script>


# re: 业务实体对象(Business Entity Object)的序列化 2004-12-13 17:42 montaque
呵呵,一般的实体类都是sealed,不会有子类。   回复   更多评论
  

# re: 业务实体对象(Business Entity Object)的序列化 2004-12-14 10:30 Ninputer
这个和引发事件要在一个protected virtual OnXXX中进行一样,是一般规则。在sealed的实体对象上恰好没有这样写结果对了,这不一定是你深思熟虑的结果,将来还是可能犯这个错误。比如ADO.NET的DataTable就犯了这个严重错误。到.NET 2.0种才改正。   回复   更多评论
  

# re: 业务实体对象(Business Entity Object)的序列化 2004-12-17 03:05 Rickie
Thanks, Ninputer and montaque.
*
I think what you said are correct. It depends on real situlation to make a decision.   回复   更多评论
  

# re: 业务实体对象(Business Entity Object)的序列化 2005-03-20 13:12 netwyh
把GetObjectData的实现隐藏起来(即使用显示实现)是非常不好的设计,这将导致它的子类无法序列化新声明的字段。
非常赞同:Ninputer的观点,我的用DataSet的时候发现这样的问题,我从DataSet继承一个新的DataSet,然后在新的DataSet中包含一个DataSet的属性,这样就会造成DataSet属性不能被序列化的问题。

不知道楼主有没有好办法?我急用!!!
# re: 业务实体对象(Business Entity Object)的序列化 2004-12-13 09:37 Ninputer  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值