C# 自定義序列化數據

由於使用默認的序列化數據,是使用反射技術來進行的。因此速度有點問題。為了,是速度提高,可以

採用自定義序列化。要實現自定義序列化,需實現ISerializable接口。

代碼如下:

View Code
    [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個方法中

要調用基類的方法。代碼如下:

View Code
    [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接口

代碼如下:

View Code
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客戶端調用代碼如下:

View Code
            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();

 

 

 

 

 

posted @ 2012-04-21 11:16  無限遐想  阅读(802)  评论(0编辑  收藏  举报