C# 自定義序列化數據
由於使用默認的序列化數據,是使用反射技術來進行的。因此速度有點問題。為了,是速度提高,可以
採用自定義序列化。要實現自定義序列化,需實現ISerializable接口。
代碼如下:
[Serializable] public class MyObject : ISerializable { public int n1; public int n2; public String str; public MyObject() { } protected MyObject(SerializationInfo info, StreamingContext context) { n1 = info.GetInt32("i"); n2 = info.GetInt32("j"); str = info.GetString("k"); } [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); } }
1.需要實現這個接口。
這個接口方法,是實現了要序列化哪些數據。
2.需要一個構造函數,構造函數是這樣的。
protected MyObject(SerializationInfo info, StreamingContext context) { n1 = info.GetInt32("i"); n2 = info.GetInt32("j"); str = info.GetString("k"); }
這個構造函數,是在類被反序列化的時候調用,在這裡可以指定要反序列化的內容。
3.調用的時候,和正常序列化一樣。
4.對應有繼承的類,實現序列化的時候,也要實現一個接口,一個構造函數。在這2個方法中
要調用基類的方法。代碼如下:
[Serializable] public class ObjectTwo : MyObject, IDeserializationCallback { public int num; public ObjectTwo() : base() { } protected ObjectTwo(SerializationInfo si, StreamingContext context) : base(si, context) { num = si.GetInt32("num"); } [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo si, StreamingContext context) { base.GetObjectData(si, context); si.AddValue("num", num); } #region IDeserializationCallback 成員 public void OnDeserialization(object sender) { num = n1 + n2; } #endregion }
注意:在GetObjectData方法上,最好加一個安全屬性
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter
= true)]。
[System.Xml.Serialization.XmlElementAttribute(Order=0)] 屬性加在屬性上,可以設置
序列化的順序。
5.為了能在反序列數據后,能執行一定的操作,需要給該類,繼承IDeserializationCallback接口
這樣,在完成反序列化數據后,能執行一個操作。這裡是在反序列化完成后,調用基類的數據,生成數據相加。
#region IDeserializationCallback 成員 public void OnDeserialization(object sender) { num = n1 + n2; } #endregion
6.在保存序列化,反序列數據可以用繼承Stream的任何類。如:FileStream文件流。MemoryStream內存流。
7.在生成序列化,反序列化,可以指定是二進制,或則sop等。如:SoapFormatter BinaryFormatter。序列化和
反序列化數據,要用相同的格式。
8.對應不想序列化的屬性,只需要加[NonSerialized]這個就可以了,那麼該屬性在序列化的時候,不會被序列化。
9.大數據序列化
9.1定義服務器端的返回數據
[XmlType(Namespace = "http://my.namespace.com/data")] public class Content { [XmlElement] public string name; [XmlElement] public string extension; [XmlElement] public byte[] data; }
其中byte[] 就是放大數據的。
9.2客戶端接受的實體,需要繼承IXmlSerializable接口
代碼如下:
public partial class Content : IXmlSerializable { private Stream stream; private string streamFileName; public Stream DataStream { set { this.stream = value; } } public Stream GetDataStream() { return File.OpenRead(this.streamFileName); } public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { reader.ReadStartElement(); //wrapping element this.name = reader.ReadElementContentAsString(); this.extension = reader.ReadElementContentAsString(); string tempFileName = Path.GetTempFileName(); this.streamFileName = tempFileName; using (FileStream fs = File.Create(tempFileName)) { byte[] buffer = new byte[1000]; int bytesRead; reader.ReadStartElement(); do { bytesRead = reader.ReadContentAsBase64(buffer, 0, buffer.Length); fs.Write(buffer, 0, bytesRead); } while (bytesRead > 0); reader.ReadEndElement(); } reader.ReadEndElement(); //wrapping element } public void WriteXml(XmlWriter writer) { writer.WriteStartElement("name"); writer.WriteValue(this.name); writer.WriteEndElement(); writer.WriteStartElement("extension"); writer.WriteValue(this.extension); writer.WriteEndElement(); writer.WriteStartElement("data"); XmlDictionaryWriter dictWriter = writer as XmlDictionaryWriter; bool isMtom = dictWriter != null && dictWriter is IXmlMtomWriterInitializer; if (isMtom) { dictWriter.WriteValue(new MyStreamProvider(this.stream)); } else { // fall back to the original behavior byte[] buffer = new byte[1000]; int bytesRead; do { bytesRead = this.stream.Read(buffer, 0, buffer.Length); if (bytesRead > 0) { writer.WriteBase64(buffer, 0, bytesRead); } } while (bytesRead > 0); } writer.WriteEndElement(); } class MyStreamProvider : IStreamProvider { Stream stream; public MyStreamProvider(Stream stream) { this.stream = stream; } public Stream GetStream() { return this.stream; } public void ReleaseStream(Stream stream) { } } }
9.3客戶端調用代碼如下:
SomeServiceClient c = new SomeServiceClient(); byte[] fileContents = new byte[100]; for (int i = 0; i < fileContents.Length; i++) { fileContents[i] = (byte)'a'; } RequestClass request = new RequestClass { id = "id", token = "token", content = new Content { name = "file", extension = "ext", //data = fileContents, DataStream = new MemoryStream(fileContents), }, }; c.SendRequest(request); ResponseClass resp = c.GetResponse(234); Console.WriteLine(resp.content.name); Stream dataStream = resp.content.GetDataStream(); string text = new StreamReader(dataStream).ReadToEnd();