关于wcf序列化后的压缩示例

序列化的方法很多,建议用ProtoBuf,百度下protobuf-net.dll下载这个组件,把它引进到我们的项目中。

怎么使用它呢?

第一步,在需要序列化的类里面增加ProtoBuf格式,例如:

[ProtoContract]
    public class WcfResult
    {

        [ProtoMember(1,IsRequired = true)]
        public int Unid{ get; set; }

        [ProtoMember(2)]
        public string Msg { get; set; }

        [ProtoMember(3)]
        public List<int> Ids{ get; set; }

        [ProtoMember(4)]
        public bool IsTrue { get; set; }
}

IsRequired表示在这个消息中这个字段是必须的,就像数据库中的非空字段一样的,必须要有值。

注意的是,类的名称上面要有[ProtoContract],属性也必须打上[ProtoMember()],否则序列化将不通过。

第二步,序列化与反序列化的方法:

public static byte[] ProtobufSerialize<T>(T obj)
{
    using (MemoryStream memory = new MemoryStream())
    {
        Serializer.Serialize<T>(memory, obj);
        return memory.ToArray();
    }
}

 public static T ProtobufDeserialize<T>(byte[] data) where T: class
{
    using (MemoryStream memory = new MemoryStream(data))
    {
        return Serializer.Deserialize<T>(memory);
    }
}

很多时候,wcf传输的对象非常巨大,需要压缩。这里只是简单的提供自带的压缩方法。大家也可以去下载ICSharpCode这个东西,研究一下。

  public static string ZipCompress(byte[] buffer)
        {
            try
            {
                string str = "";
                using (MemoryStream ms = new MemoryStream())
                {
                    using (GZipStream gzipStream = new GZipStream(ms, CompressionMode.Compress, true))
                    {
                        gzipStream.Write(buffer, 0, buffer.Length);
                    }
                    ms.Flush();
                    str = Convert.ToBase64String(ms.ToArray());
                }
                return str;
            }
            catch (Exception exp)
            {
                return null;
            }
        }

        public static byte[] UNZip(string str)
        {
            try
            {
                MemoryStream reMs = new MemoryStream();
                byte[] buffer = Convert.FromBase64String(str);
                using (MemoryStream ms = new MemoryStream(buffer))
                {
                    using (GZipStream gzipStream = new GZipStream(ms, CompressionMode.Decompress))
                    {
                        byte[] tmpBuffer = new byte[4096]; 
                        int offset = 0;
                        while ((offset = gzipStream.Read(tmpBuffer, 0, tmpBuffer.Length)) > 0)
                        {
                            reMs.Write(tmpBuffer, 0, offset);
                        }
                    }
                }
                reMs.Flush();
                return reMs.ToArray();
            }
            catch (Exception exp)
            {
                return null;
            }
        }

最后,我们把整个例子串起来,代码如下。

//对象(1)
WcfResult wcf = new WcfResult({Unid=123,Msg="hello contra!"});
//序列化(2)
byte[] buffer = ProtobufSerialize(wcf);
//压缩(3)
string tmpwcf = ZipHelper.ZipCompress(buffer);
//解压缩(4)
byte[] tmpbuffer = ZipHelper.UNZip(tmpwcf);
//反序列化(5)
WcfResult ret = ProtobufDeserialize(tmpbuffer);

(2)(3)放在wcf服务端。

(4)(5)wcf客户端代码,提供dll给远程客户端调用。

 

完成了,测试一下,对于纯数字的实体压缩率不是很高。。好吧。。有空再研究。

 

posted @ 2012-06-14 16:18  魂斗罗II  阅读(357)  评论(0编辑  收藏  举报