using CYQ.Data.Tool; using System; using System.IO; using System.IO.Compression; using System.Runtime.Serialization.Formatters.Binary; using System.Text; namespace CYQ.Data.Cache { internal enum SerializedType : ushort { None = 255, ByteArray = 0, Object = 1, String = 2, Datetime = 3, Bool = 4, //SByte = 5, //Makes no sense. Byte = 6, Short = 7, UShort = 8, Int = 9, UInt = 10, Long = 11, ULong = 12, Float = 13, Double = 14, ObjectJson = 15, CompressedByteArray = 50, CompressedObject = 51, CompressedString = 52, CompressedObjectJson = 53, } internal class Serializer { /// /// 序列化 /// /// 值 /// 返回序列化类型 /// 指定超过长度时启用压缩功能 /// public static byte[] Serialize(object value, out SerializedType type, uint compressionThreshold) { byte[] bytes; if (value is byte[]) { bytes = (byte[])value; type = SerializedType.ByteArray; if (bytes.Length > compressionThreshold) { bytes = compress(bytes); type = SerializedType.CompressedByteArray; } } else if (value is string) { bytes = Encoding.UTF8.GetBytes((string)value); type = SerializedType.String; if (bytes.Length > compressionThreshold) { bytes = compress(bytes); type = SerializedType.CompressedString; } } else if (value is DateTime) { bytes = BitConverter.GetBytes(((DateTime)value).Ticks); type = SerializedType.Datetime; } else if (value is bool) { bytes = new byte[] { (byte)((bool)value ? 1 : 0) }; type = SerializedType.Bool; } else if (value is byte) { bytes = new byte[] { (byte)value }; type = SerializedType.Byte; } else if (value is short) { bytes = BitConverter.GetBytes((short)value); type = SerializedType.Short; } else if (value is ushort) { bytes = BitConverter.GetBytes((ushort)value); type = SerializedType.UShort; } else if (value is int) { bytes = BitConverter.GetBytes((int)value); type = SerializedType.Int; } else if (value is uint) { bytes = BitConverter.GetBytes((uint)value); type = SerializedType.UInt; } else if (value is long) { bytes = BitConverter.GetBytes((long)value); type = SerializedType.Long; } else if (value is ulong) { bytes = BitConverter.GetBytes((ulong)value); type = SerializedType.ULong; } else if (value is float) { bytes = BitConverter.GetBytes((float)value); type = SerializedType.Float; } else if (value is double) { bytes = BitConverter.GetBytes((double)value); type = SerializedType.Double; } else { type = SerializedType.ObjectJson; Type t = value.GetType(); switch (ReflectTool.GetSystemType(ref t)) { case SysType.Base: case SysType.Enum: case SysType.Custom: if (t.GetCustomAttributes(typeof(SerializableAttribute), false).Length > 0) { type = SerializedType.Object; } break; } if (type == SerializedType.Object) { //可序列化 List 如果 object 不支持序列化,会挂。 using (MemoryStream ms = new MemoryStream()) { new BinaryFormatter().Serialize(ms, value); bytes = ms.ToArray(); if (bytes.Length > compressionThreshold) { bytes = compress(bytes); type = SerializedType.CompressedObject; } } } else { string json = JsonHelper.ToJson(value); bytes = Encoding.UTF8.GetBytes(json); if (bytes.Length > compressionThreshold) { bytes = compress(bytes); type = SerializedType.CompressedObjectJson; } } } return bytes; } private static byte[] compress(byte[] bytes) { using (MemoryStream ms = new MemoryStream()) { using (DeflateStream gzs = new DeflateStream(ms, CompressionMode.Compress, false)) { gzs.Write(bytes, 0, bytes.Length); } ms.Close(); return ms.ToArray(); } } private static byte[] decompress(byte[] bytes) { using (MemoryStream ms = new MemoryStream(bytes, false)) { using (DeflateStream gzs = new DeflateStream(ms, CompressionMode.Decompress, false)) { using (MemoryStream dest = new MemoryStream()) { byte[] tmp = new byte[bytes.Length]; int read; while ((read = gzs.Read(tmp, 0, tmp.Length)) != 0) { dest.Write(tmp, 0, read); } dest.Close(); return dest.ToArray(); } } } } public static object DeSerialize(byte[] bytes, SerializedType type) { switch (type) { case SerializedType.String: return Encoding.UTF8.GetString(bytes); case SerializedType.Datetime: return new DateTime(BitConverter.ToInt64(bytes, 0)); case SerializedType.Bool: return bytes[0] == 1; case SerializedType.Byte: return bytes[0]; case SerializedType.Short: return BitConverter.ToInt16(bytes, 0); case SerializedType.UShort: return BitConverter.ToUInt16(bytes, 0); case SerializedType.Int: return BitConverter.ToInt32(bytes, 0); case SerializedType.UInt: return BitConverter.ToUInt32(bytes, 0); case SerializedType.Long: return BitConverter.ToInt64(bytes, 0); case SerializedType.ULong: return BitConverter.ToUInt64(bytes, 0); case SerializedType.Float: return BitConverter.ToSingle(bytes, 0); case SerializedType.Double: return BitConverter.ToDouble(bytes, 0); case SerializedType.Object: using (MemoryStream ms = new MemoryStream(bytes)) { return new BinaryFormatter().Deserialize(ms); } case SerializedType.ObjectJson: return Encoding.UTF8.GetString(bytes); case SerializedType.CompressedByteArray: return DeSerialize(decompress(bytes), SerializedType.ByteArray); case SerializedType.CompressedString: return DeSerialize(decompress(bytes), SerializedType.String); case SerializedType.CompressedObject: return DeSerialize(decompress(bytes), SerializedType.Object); case SerializedType.CompressedObjectJson: return DeSerialize(decompress(bytes), SerializedType.ObjectJson); case SerializedType.ByteArray: default: return bytes; } } } }