您的位置:首页 > 其它

学习笔记[序列化].NET Framework 开发员指南

2005-10-24 09:57 375 查看
让我奇怪的是.net高级编程里居然没有序列化,也可能是太疲倦了,注意力不集中吧.可恶,为什么这么困呢?!
令一个类可序列化的最简单的方式是按如下所示使用 Serializable 属性标记它。
[Serializable]
public class MyObject {
public int n1 = 0;
public int n2 = 0;
public String str = null;
}
以下代码示例说明该类的实例是如何被序列化到一个文件中的。
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
该示例使用二进制格式化程序执行序列化。您需要做的所有工作就是创建流的实例和您想要使用的格式化程序,然后对该格式化程序调用 Serialize 方法。要序列化的流和对象作为参数提供给该调用。尽管在此示例中并没有显式阐释这一点,但一个类的所有成员变量都将被序列化,即使是那些已被标记为私有的变量。在此方面,二进制序列化不同于 XMLSerializer 类,后者只序列化公共字段。有关从二进制序列化中排除成员变量的信息,请参见有选择的序列化。
将对象还原回其以前的状态十分简单。首先,创建用于读取的流和格式化程序,然后指示格式化程序反序列化该对象。下面的代码示例说明如何执行上述的操作。
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(stream);
stream.Close();
// Here's the proof.
Console.WriteLine("n1: {0}", obj.n1);
Console.WriteLine("n2: {0}", obj.n2);
Console.WriteLine("str: {0}", obj.str);
上面所用的 BinaryFormatter 非常有效,它生成了非常简洁的字节流。通过该格式化程序序列化的所有对象都还可以通过该格式化程序被反序列化,这使该工具对于序列化将在 .NET 平台上被反序列化的对象而言十分理想。需要特别注意的是,在反序列化一个对象时不调用构造函数。出于性能方面的原因对反序列化施加了该约束。但是,这违反了运行库生成的与对象编写器有关的一些通常协定,并且开发人员应确保他们在将对象标记为可序列化时理解其后果。
如果可移植性是必需的,则代之以使用 SoapFormatter。只需用 SoapFormatter 代替上面代码中的 BinaryFormatter,并且如前面一样调用 Serialize 和 Deserialize。此格式化程序为上面使用的示例生成以下输出。
<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/"
SOAP-ENV:encodingStyle=
"http://schemas.microsoft.com/soap/encoding/clr/1.0"
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:a1="http://schemas.microsoft.com/clr/assem/ToFile">
<SOAP-ENV:Body>
<a1:MyObject id="ref-1">
<n1>1</n1>
<n2>24</n2>
<str id="ref-3">Some String</str>
</a1:MyObject>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
需要特别注意的是,Serializable 属性不能被继承。如果我们从 MyObject 派生一个新类,此新类必须也用该属性标记,否则它不能被序列化。例如,当您试图序列化下面的类的实例时,您将获得 SerializationException,它通知您 MyStuff 类型没有被标记为可序列化。
public class MyStuff : MyObject
{
public int n3;
}
使用 Serializable 属性十分方便,但它具有上面所述的局限性。有关何时应将类标记为进行序列化的信息,请参考序列化指南;在对类进行编译后,就不能再向该类添加序列化。

标记[Serializable]和序列化
System.SerializableAttribute
全部显示
指示一个类可以序列化,无法继承此类。
线程安全
此类型的所有公共静态(Visual Basic 中为 Shared)成员对多线程操作而言都是安全的。但不保证任何实例成员是线程安全的。
备注
将 SerializableAttribute 属性应用于一个类型可指示该类型的实例可以序列化。如果正在序列化的对象图中的任何类型未应用 SerializableAttribute 属性,公共语言运行库则会引发 SerializationException。
即使该类也会实现 ISerializable 接口来控制序列化进程,仍要应用 SerializableAttribute 属性。
默认情况下,类型中由 SerializableAttribute 标记的所有公共和私有字段都会进行序列化,除非该类型实现 ISerializable 接口来重写序列化进程。默认的序列化进程会排除用 NonSerializedAttribute 属性标记的字段。如果可序列化类型的字段包含指针、句柄或其他某些针对于特定环境的数据结构,并且不能在不同的环境中以有意义的方式重建,则最好将 NonSerializedAttribute 属性应用于该字段。
有关使用属性的更多信息,请参见利用属性扩展元数据。有关序列化的更多信息,请参见 System.Runtime.Serialization 命名空间。
示例
下面的示例阐释用 SerializableAttribute 属性标记的对象的序列化。若要使用 BinaryFormatter 而不是 SoapFormatter,请取消注释相应的行。
[C#]
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
//using System.Runtime.Serialization.Formatters.Binary;
public class Test {
public static void Main() {
//Creates a new TestSimpleObject object.
TestSimpleObject obj = new TestSimpleObject();
Console.WriteLine("Before serialization the object contains: ");
obj.Print();
//Opens a file and serializes the object into it in binary format.
Stream stream = File.Open("data.xml", FileMode.Create);
SoapFormatter formatter = new SoapFormatter();
//BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Close();

//Empties obj.
obj = null;

//Opens file "data.xml" and deserializes the object from it.
stream = File.Open("data.xml", FileMode.Open);
formatter = new SoapFormatter();
//formatter = new BinaryFormatter();
obj = (TestSimpleObject)formatter.Deserialize(stream);
stream.Close();
Console.WriteLine("");
Console.WriteLine("After deserialization the object contains: ");
obj.Print();
}
}

// A test object that needs to be serialized.
[Serializable()]
public class TestSimpleObject {
public int member1;
public string member2;
public string member3;
public double member4;

// A field that is not serialized.
[NonSerialized()] public string member5;

public TestSimpleObject() {
member1 = 11;
member2 = "hello";
member3 = "hello";
member4 = 3.14159265;
member5 = "hello world!";
}

public void Print() {
Console.WriteLine("member1 = '{0}'", member1);
Console.WriteLine("member2 = '{0}'", member2);
Console.WriteLine("member3 = '{0}'", member3);
Console.WriteLine("member4 = '{0}'", member4);
Console.WriteLine("member5 = '{0}'", member5);
}
}

以上抄自msdn 尽以此回顾序列化的知识
==================================================================================================
简单的理解就是把该类中的所有属性按顺序存起来,不知道底层是不是压栈的."取的时候再出栈呗"那存地址类的变量当然就不能够序列化了,因为环境是会变化的嘛.所以可以用两种标记 [Serializable]对类标记序列化 和 [NonSerialized]不能被序列化.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: