关于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给远程客户端调用。
完成了,测试一下,对于纯数字的实体压缩率不是很高。。好吧。。有空再研究。