一、为什么要使用序列化?
最重要的两个原因是:将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本;按值将对象从一个应用程序域发送至另一个应用程序域。例如,序列化可用于在 ASP.NET 中保存会话状态,以及将对象复制到 Windows 窗体的剪贴板中。它还可用于按值将对象从一个应用程序域远程传递至另一个应用程序域。本文简要介绍了 Microsoft .NET 中使用简介
序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。
在面向对象的环境中实现序列化机制时,必须在易用性和灵活性之间进行一些权衡。只要您对此过程有足够的控制能力,就可以使该过程在很大程度上自动进行。例如,简单的二进制序列化不能满足需要,或者,由于特定原因需要确定类中那些字段需要序列化。以下各部分将探讨 .NET 框架提供的可靠的序列化机制,并着重介绍使您可以根据需要自定义序列化过程的一些重要功能。
二、持久存储
我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。
公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable。否则,当序列化程序试图序列化未标记的对象时将会出现异常。
当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。
三、按值封送
对象仅在创建对象的应用程序域中有效。除非对象是从 MarshalByRefObject 派生得到或标记为 Serializable,否则,任何将对象作为参数传递或将其作为结果返回的尝试都将失败。如果对象标记为 Serializable,则该对象将被自动序列化,并从一个应用程序域传输至另一个应用程序域,然后进行反序列化,从而在第二个应用程序域中产生出该对象的一个精确副本。此过程通常称为按值封送。
如果对象是从 MarshalByRefObject 派生得到,则从一个应用程序域传递至另一个应用程序域的是对象引用,而不是对象本身。也可以将从 MarshalByRefObject 派生得到的对象标记为 Serializable。远程使用此对象时,负责进行序列化并已预先配置为 SurrogateSelector 的格式化程序将控制序列化过程,并用一个代理替换所有从 MarshalByRefObject 派生得到的对象。如果没有预先配置为 SurrogateSelector,序列化体系结构将遵从下面的标准序列化规则。
四、序列化过程的步骤
在格式化程序上调用 Serialize 方法时,对象序列化按照以下规则进行:
· 检查格式化程序是否有代理选取器。如果有,检查代理选取器是否处理指定类型的对象。如果选取器处理此对象类型,将在代理选取器上调用 ISerializable.GetObjectData。
· 如果没有代理选取器或有却不处理此类型,将检查是否使用 Serializable 属性对对象进行标记。如果未标记,将会引发 SerializationException。
· 如果对象已被正确标记,将检查对象是否实现了 ISerializable。如果已实现,将在对象上调用 GetObjectData。
· 如果对象未实现 Serializable,将使用默认的序列化策略,对所有未标记为 NonSerialized 的字段都进行序列化。
五、版本控制
.NET 框架支持版本控制和并排执行,并且,如果类的接口保持一致,所有类均可跨版本工作。由于序列化涉及的是成员变量而非接口,所以,在向要跨版本序列化的类中添加成员变量,或从中删除变量时,应谨慎行事。特别是对于未实现 ISerializable 的类更应如此。若当前版本的状态发生了任何变化(例如添加成员变量、更改变量类型或更改变量名称),都意味着如果同一类型的现有对象是使用早期版本进行序列化的,则无法成功对它们进行反序列化。
如果对象的状态需要在不同版本间发生改变,类的作者可以有两种选择:
· 实现 ISerializable。这使您可以精确地控制序列化和反序列化过程,在反序列化过程中正确地添加和解释未来状态。
· 使用 NonSerialized 属性标记不重要的成员变量。仅当预计类在不同版本间的变化较小时,才可使用这个选项。例如,把一个新变量添加至类的较高版本后,可以将该变量标记为 NonSerialized,以确保该类与早期版本保持兼容。
六、序列化规则
由于类编译后便无法序列化,所以在设计新类时应考虑序列化。需要考虑的问题有:是否必须跨应用程序域来发送此类?是否要远程使用此类?用户将如何使用此类?也许他们会从我的类中派生出一个需要序列化的新类。只要有这种可能性,就应将类标记为可序列化。除下列情况以外,最好将所有类都标记为可序列化:
· 所有的类都永远也不会跨越应用程序域。如果某个类不要求序列化但需要跨越应用程序域,请从 MarshalByRefObject 派生此类。
· 类存储仅适用于其当前实例的特殊指针。例如,如果某个类包含非受控的内存或文件句柄,请确保将这些字段标记为 NonSerialized 或根本不序列化此类。
· 某些数据成员包含敏感信息。在这种情况下,建议实现 ISerializable 并仅序列化所要求的字段。
上面那些东西来自网上不过和MSDN上说的差不多的,下面写点自己的东西要不这篇文章彻头彻尾的转帖了啊!
1.序列化有:二进制序列化,soap,xml,自定义。
Soap序列化和二进制的使用是一样的,只是soap生成的是xml文件可以浏览而二进制的不能浏览。还有soap序列化要自己添加引用
2.XML 序列化不转换方法、索引器、私有字段或只读属性(只读集合除外)。要序列化对象的所有字段和属性(公共的和私有的),请使用
使用 XmLSerializer 类可将下列项序列化:
- 公共类的公共读/写属性和字段
- 实现 ICollection 或 IEnumerable 的类
注意:只有集合会被序列化,而公共属性却不会。
- XmlElement 对象
- XmlNode 对象
- DataSet 对象
[XmlAttribute(AttributeName="员工姓名")] //属性
[XmlElement(ElementName="员工姓名")] //元素
废话少说了还是把code贴出来了!
主要就是Company.cs,department.cs,TestCustomSerialize .cs(自定义序列化类),web页面
Company.cs(类库):
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Serialization;
/// <summary>
/// Company 的摘要说明
/// </summary>
[XmlRoot(Namespace="http://www.cpdyj.com",ElementName="BitTime")]//ElementName指定根结点名称
public class Company
{
public Company()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
private string _companyName;
[XmlElement(ElementName="公司名称")]//指定元素名称
public string CompanyName
{
get { return _companyName; }
set { _companyName = value; }
}
private string _companyAddress;
[XmlElement(ElementName = "公司地址")]
public string CompanyAddress
{
get { return _companyAddress; }
set { _companyAddress = value; }
}
private string _companyPostCode="100085";
[XmlElement(ElementName = "邮政编码")]
public string CompanyPostCode
{
get { return _companyPostCode; }
set { _companyPostCode = value; }
}
private string _companyBoss;
[XmlElement(ElementName = "法人代表")]
///<summmary>
///法人代表
///</summary>
public string CompanyBoss
{
get { return _companyBoss; }
set { _companyBoss = value; }
}
//下面属性与department类进行关联
private Department[] _depart;
[XmlElement(ElementName="部门名称")]
public Department[] Depart
{
get{return _depart;}
set{_depart = value;}
}
}
Department.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Serialization;
/// <summary>
/// Department 的摘要说明
/// </summary>
public class Department
{
public Department()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
private string _departmentName;
[XmlAttribute(AttributeName="部门")]
//[XmlElement(ElementName = "部门")]
public string DepartmentName
{
get { return _departmentName; }
set { _departmentName = value; }
}
private string workerName;
//[XmlAttribute(AttributeName="员工姓名")]
[XmlElement(ElementName = "员工姓名")]
public string WorkerName
{
get { return workerName; }
set { workerName = value; }
}
private int _age;
// [XmlAttribute(AttributeName="年龄")]
[XmlElement(ElementName = "年龄")]
public int Age
{
get { return _age; }
set { _age = value; }
}
}
TestCustomSerialize.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Runtime.Serialization;
using System.Security.Permissions;
/// <summary>
/// TestCustomSerialize 的摘要说明
/// </summary>
public class TestCustomSerialize : ISerializable
{
public TestCustomSerialize()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public int n1;
public int n2;
public string str;
public DateTime date;
public TestCustomSerialize(SerializationInfo info, StreamingContext context)
{
n1=info.GetInt32("i");
n2=info.GetInt32("j");
str=info.GetString("k");
date = info.GetDateTime("dateTime").ToLocalTime();
}
#region ISerializable 成员
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("i",n1);
info.AddValue("j",n2);
info.AddValue("k",str);
info.AddValue("dateTime", date);
}
#endregion
}
Web页面(前台就是几个按钮,别浪费页面了)
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
using System.Xml.Serialization;
public partial class 序列化 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
//二进制序列化
protected void Button1_Click(object sender, EventArgs e)
{
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(@"D:/Bit/Log4net/formatter.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
}
//二进制反序列化
protected void Button2_Click(object sender, EventArgs e)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(@"D:/Bit/Log4net/formatter.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject)formatter.Deserialize(stream);
stream.Close();
Response.Write(obj.n1 + " " + obj.n2 + " " + obj.str);
}
//soap序列化
protected void Button5_Click(object sender, EventArgs e)
{
//soap序列化与二进制一样只是生成的是xml文件而不是二进制代码
//使用soap序列化时必须添加System.Runtime.Serialization.Formatters.Soap的引用,然后引用该命名空间
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream(@"D:/Bit/Log4net/formatter.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
}
//soap反序列化
protected void Button6_Click(object sender, EventArgs e)
{
IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream(@"D:/Bit/Log4net/formatter.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject)formatter.Deserialize(stream);
stream.Close();
Response.Write(obj.n1 + " " + obj.n2 + " " + obj.str);
}
//xml序列化
protected void Button3_Click(object sender, EventArgs e)
{
Company company = new Company();
company.CompanyName = "北京";
company.CompanyBoss = "海淀";
company.CompanyAddress = "北京海淀区苏州街北段";
XmlSerializer xml = new XmlSerializer(typeof(Company));
Stream stream = new FileStream(Server.MapPath("company.xml"), FileMode.Create, FileAccess.Write, FileShare.None);
xml.Serialize(stream, company);
stream.Close();
}
//xml反序列化
protected void Button4_Click(object sender, EventArgs e)
{
XmlSerializer xml = new XmlSerializer(typeof(Company));
Stream stream = new FileStream(Server.MapPath("company.xml"), FileMode.Open, FileAccess.Read, FileShare.Read);
Company company = (Company)xml.Deserialize(stream);
Response.Write(company.CompanyAddress + "," + company.CompanyBoss + "," + company.CompanyName + "," + company.CompanyPostCode);
}
protected void Button7_Click(object sender, EventArgs e)
{
Company company = new Company();
company.CompanyName = "北京";
company.CompanyBoss = "海淀";
company.CompanyAddress = "北京海淀区苏州街北段";
//实例化Department类
Department d1 = new Department();
d1.Age = 30;
d1.WorkerName = "Hello";
d1.DepartmentName = "技术部";
Department d2 = new Department();
d2.Age = 30;
d2.WorkerName = "Hello";
d2.DepartmentName = "技术部";
Department d3 = new Department();
d3.Age = 30;
d3.WorkerName = "Hello";
d3.DepartmentName = "技术部";
Department d4 = new Department();
d4.Age = 30;
d4.WorkerName = "Hello";
d4.DepartmentName = "技术部";
Department d5 = new Department();
d5.Age = 30;
d5.WorkerName = "Hello";
d5.DepartmentName = "技术部";
Department d6 = new Department();
d6.Age = 30;
d6.WorkerName = "Hello";
d6.DepartmentName = "技术部";
Department d7 = new Department();
d7.Age = 30;
d7.WorkerName = "Hello";
d7.DepartmentName = "技术部";
Department[] d ={ d1, d2, d3, d4, d5, d6, d7 };
company.Depart = d;
XmlSerializer xml = new XmlSerializer(typeof(Company));
FileStream stream = new FileStream(Server.MapPath("company.xml"), FileMode.Create);
xml.Serialize(stream, company);
stream.Close();
}
//xml反序列化(有两个类关联)
protected void Button8_Click(object sender, EventArgs e)
{
}
//自定义序列化
protected void Button9_Click(object sender, EventArgs e)
{
//自定义序列化主要是类的写法不一样,调用的方法是一样的
XmlSerializer xml = new XmlSerializer(typeof(TestCustomSerialize));
string file = Server.MapPath("custom.xml");
if (!File.Exists(file))
{
File.Create(file);
}
else
{
Stream stream = new FileStream(file, FileMode.Create,FileAccess.Write,FileShare.ReadWrite);
TestCustomSerialize custom = new TestCustomSerialize();
custom.str = "欢迎你光临";
custom.n1 = 2000;
custom.n2 = 1000;
custom.date = DateTime.Now;
xml.Serialize(stream, custom);
stream.Close();
}
}
//自定义反序列化
protected void Button10_Click(object sender, EventArgs e)
{
string file = Server.MapPath("custom.xml");
Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None);
XmlSerializer xml = new XmlSerializer(typeof(TestCustomSerialize));
TestCustomSerialize test = (TestCustomSerialize)xml.Deserialize(stream);
Response.Write("反序列化结果:" + test.n1 + "," + test.n2 + "," + test.str + ",当前日期是:" + test.date);
stream.Close();
}
}
代码太多了!!!!!慢慢看吧,这可是在vs2005上调试通过,然后贴过来的啊!
下面的代码是在http://www.cnblogs.com/freeliver54/archive/2007/05/22/755134.html看到的,就贴到一起了啊!
1.将DataSet对象序列化到二进制文件
2.将二进制文件序列化到DataSet对象
3.将DataSet中的数据写到XML文件
4.将数据XML文件读到DataSet对象
5.将DataSet中的数据及架构写到XML文件
6.将数据及架构XML文件读到DataSet对象
7.将DataSet中的数据及架构分别写到不同的XML文件
8.将相关的数据及架构XML文件读到DataSet对象
================================
// 1.将DataSet对象序列化到二进制文件
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection myConn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=TestDB;User ID=sa;Password=sa");
SqlDataAdapter myda = new SqlDataAdapter("select personName,personAge from person", myConn);
DataSet myds = new DataSet();
myConn.Open();
myda.Fill(myds);
myConn.Close();
myds.RemotingFormat = SerializationFormat.Binary;
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.StreamWriter swBinary = new System.IO.StreamWriter("D://DataSetBinary.dat");
bf.Serialize(swBinary.BaseStream, myds);
swBinary.Close();
}
// 2.将二进制文件序列化到DataSet对象
protected void Button2_Click(object sender, EventArgs e)
{
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
System.IO.FileStream fsBinary = new System.IO.FileStream("D://DataSetBinary.dat", System.IO.FileMode.Open);
DataSet myds = (DataSet)bf.Deserialize(fsBinary);
this.GridView2.DataSource = myds;
this.GridView2.DataBind();
}
// 3.将DataSet中的数据写到XML文件
protected void Button3_Click(object sender, EventArgs e)
{
SqlConnection myConn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=TestDB;User ID=sa;Password=sa");
SqlDataAdapter myda = new SqlDataAdapter("select personName,personAge from person", myConn);
DataSet myds = new DataSet();
myConn.Open();
myda.Fill(myds);
myConn.Close();
myds.WriteXml("D://DataSetXmlData.xml");
}
// 4.将数据XML文件读到DataSet对象
protected void Button4_Click(object sender, EventArgs e)
{
DataSet myds = new DataSet();
myds.ReadXml("D://DataSetXmlData.xml");
this.GridView2.DataSource = myds;
this.GridView2.DataBind();
}
// 5.将DataSet中的数据及架构写到XML文件
protected void Button5_Click(object sender, EventArgs e)
{
SqlConnection myConn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=TestDB;User ID=sa;Password=sa");
SqlDataAdapter myda = new SqlDataAdapter("select personName,personAge from person", myConn);
DataSet myds = new DataSet();
myConn.Open();
myda.Fill(myds);
myConn.Close();
myds.WriteXml("D://DataSetXmlDataSchema.xml", XmlWriteMode.WriteSchema);
}
// 6.将数据及架构XML文件读到DataSet对象
protected void Button6_Click(object sender, EventArgs e)
{
DataSet myds = new DataSet();
myds.ReadXml("D://DataSetXmlDataSchema.xml",XmlReadMode.ReadSchema);
this.GridView2.DataSource = myds;
this.GridView2.DataBind();
}
// 7.将DataSet中的数据及架构分别写到不同的XML文件
protected void Button7_Click(object sender, EventArgs e)
{
SqlConnection myConn = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=TestDB;User ID=sa;Password=sa");
SqlDataAdapter myda = new SqlDataAdapter("select personName,personAge from person", myConn);
DataSet myds = new DataSet();
myConn.Open();
myda.Fill(myds);
myConn.Close();
myds.WriteXmlSchema("D://DataSetXmlSchemaOnly.xml");
myds.WriteXml("D://DataSetXmlDataOnly.xml");
}
// 8.将相关的数据及架构XML文件读到DataSet对象
protected void Button8_Click(object sender, EventArgs e)
{
DataSet myds = new DataSet();
myds.ReadXmlSchema("D://DataSetXmlSchemaOnly.xml");
myds.ReadXml("D://DataSetXmlDataSchema.xml");
this.GridView2.DataSource = myds;
this.GridView2.DataBind();
}
//xml 序列化(有两个类关联)