二、SoapFormatter
前面我们用BinaryFormatter以二进制格式来序列化。很容易的我们就能把前面的例子改为用SoapFormatter的,这样将以xml格式化,因此能有更好的可移植性。所要做的更改只是将以上代码中的格式化程序换成 SoapFormatter,而 Serialize 和 Deserialize 调用不变。对于上面使用的示例,该格式化程序将生成以下结果。
在这里需要注意的是,无法继承 Serializable 属性。如果从 MyObject 派生出一个新的类,则这个新的类也必须使用该属性进行标记,否则将无法序列化。例如,如果试图序列化以下类实例,将会显示一个 SerializationException,说明 MyStuff 类型未标记为可序列化。<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">一些字符串</str> </a1:MyObject> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
然而关于格式化器,还有个问题,假设我们只需要xml,但不需要soap特有的额外信息,那么该怎么做?有两个方案:1、编写一个实现 IFormatter接口的类,采用的方式类似于SoapFormatter,但是可以没有你不需要的信息;2、使用框架提供的类 XmlSerializer。public class MyStuff : MyObject { public int n3; }
XmlSerializer类和前两个主流的序列化类的几个不同点是:
1、不需要Serializable属性,Serializable和NonSerializable属性将会被忽略,但是使用XmlIgnore属性,和NonSerializable属性类似。
2、该类不能安全地访问私有变成员,所以学要将私有成员改为公共成员,或者提供合适的公共特性。
3、要求被序列化的类要有一个默认的构造器。
我们改一下前面的MyObject类为:
现在我们用XmlSerializer类来对修改后的MyObject进行序列化。因为XmlSerializer类的构造器里有个Type参数,所以 XmlSerializer对象被明确的连到该Type参数所表示的类了。XmlSerializer类也有Serialize和Deserialize方法:public class MyObject { public int n1; public String str; public MyObject(){} public MyObject(n1,str) { this.n1=n1; this.str=str; } public override string ToString() { return String.Format("{0}:{1}",this.str,this.n1); } }
MyObject obj = new MyObject(12,"some string..."); XmlSerializer formatter = new XmlSerializer(typeof(MyObject)); Stream stream = new FileStream("MyFile.xml", FileMode.Create, FileAccess.Write, FileShare.None); formatter.Serialize(stream, obj); //下面是反序列化 stream.Seek(0,SeekOrigin.Begin) MyObject obj_out=(MyObject)formatter.Deserialize(stream) stream.Close(); Console.WriteLine(obj_out);