/// <summary>把消息写入流中,默认调用序列化框架</summary> /// <param name="stream">数据流</param> /// <param name="rwkind">序列化类型</param> protected virtual void OnWrite(Stream stream, RWKinds rwkind) { var writer = RWService.CreateWriter(rwkind); writer.Stream = stream; OnReadWriteSet(writer); writer.Settings.Encoding = new UTF8Encoding(false); if (Debug) { writer.Debug = true; writer.EnableTraceStream(); } writer.WriteObject(this); writer.Flush(); }
/// <summary>从流中读取消息内容,默认调用序列化框架</summary> /// <param name="stream"></param> /// <param name="rwkind"></param> /// <returns></returns> protected virtual Boolean OnRead(Stream stream, RWKinds rwkind) { var reader = RWService.CreateReader(rwkind); reader.Stream = stream; OnReadWriteSet(reader); if (Debug) { reader.Debug = true; reader.EnableTraceStream(); } // 传msg进去,因为是引用类型,所以问题不大 Object msg = this; return(reader.ReadObject(msg.GetType(), ref msg, null)); }
///// <summary>序列化当前消息到流中</summary> ///// <param name="stream"></param> //public void Write(Stream stream) { Write(stream, SerializationKinds.Binary); } /// <summary>序列化当前消息到流中</summary> /// <param name="stream"></param> /// <param name="rwkind"></param> public void Write(Stream stream, RWKinds rwkind = RWKinds.Binary) { //var writer = new BinaryWriterX(stream); var writer = RWService.CreateWriter(rwkind); writer.Stream = stream; Set(writer.Settings); writer.Settings.Encoding = new UTF8Encoding(false); if (Debug) { writer.Debug = true; writer.EnableTraceStream(); } // 二进制增加头部 if (rwkind == RWKinds.Binary) { // 判断并写入消息头 if (_Header != null && _Header.UseHeader) { Header.Write(writer.Stream); } // 基类写入编号,保证编号在最前面 writer.Write((Byte)Kind); } else { var n = (Byte)Kind; var bts = Encoding.ASCII.GetBytes(n.ToString()); stream.Write(bts, 0, bts.Length); } writer.WriteObject(this); writer.Flush(); }
///// <summary>从流中读取消息</summary> ///// <param name="stream">数据流</param> ///// <returns></returns> //public static Message Read(Stream stream) { return Read(stream, false); } /// <summary>从流中读取消息</summary> /// <param name="stream">数据流</param> /// <param name="rwkind"></param> /// <param name="ignoreException">忽略异常。如果忽略异常,读取失败时将返回空,并还原数据流位置</param> /// <returns></returns> public static Message Read(Stream stream, RWKinds rwkind = RWKinds.Binary, Boolean ignoreException = false) { if (stream == null || stream.Length - stream.Position < 1) { return(null); } //var reader = new BinaryReaderX(stream); var reader = RWService.CreateReader(rwkind); reader.Stream = stream; Set(reader.Settings); if (Debug) { reader.Debug = true; reader.EnableTraceStream(); } var start = stream.Position; // 消息类型,不同序列化方法的识别方式不同 MessageKind kind = (MessageKind)0; Type type = null; MessageHeader header = null; if (rwkind == RWKinds.Binary) { // 检查第一个字节 //var ch = reader.Reader.PeekChar(); var ch = stream.ReadByte(); if (ch < 0) { return(null); } stream.Seek(-1, SeekOrigin.Current); var first = (Byte)ch; #region 消息头部扩展 // 第一个字节的最高位决定是否扩展 if (MessageHeader.IsValid(first)) { try { header = new MessageHeader(); header.Read(reader.Stream); } catch { stream.Position = start; return(null); } // 如果使用了消息头,判断一下数据流长度是否满足 if (header.HasFlag(MessageHeader.Flags.Length) && header.Length > stream.Length - stream.Position) { stream.Position = start; return(null); } } #endregion // 读取了响应类型和消息类型后,动态创建消息对象 kind = (MessageKind)(reader.ReadByte() & 0x7F); } else { // 前面的数字表示消息种类 var sb = new StringBuilder(); Char c; while (true) { c = (Char)stream.ReadByte(); if (c < '0' || c > '9') { break; } sb.Append(c); } // 多读了一个,退回去 stream.Seek(-1, SeekOrigin.Current); kind = (MessageKind)Convert.ToByte(sb.ToString()); //var s = stream.IndexOf(new Byte[] { (Byte)'<' }); //if (s >= 0) //{ // var e = stream.IndexOf(new Byte[] { (Byte)'>' }, s + 1); // if (e >= 0) // { // stream.Position = s; // var msgName = Encoding.UTF8.GetString(stream.ReadBytes(e - s - 1)); // if (!String.IsNullOrEmpty(msgName) && !msgName.Contains(" ")) type = TypeX.GetType(msgName); // } //} //var settings = new XmlReaderSettings(); //settings.IgnoreWhitespace = true; //settings.IgnoreComments = true; //var xr = XmlReader.Create(stream, settings); //while (xr.NodeType != XmlNodeType.Element) { if (!xr.Read())break; } //stream.Position = start; } #region 识别消息类型 if (type == null) { type = ObjectContainer.Current.ResolveType <Message>(kind); } if (type == null) { if (ignoreException) { stream.Position = start; return(null); } else { throw new XException("无法识别的消息类型(Kind={0})!", kind); } } #endregion #region 读取消息 Message msg; if (stream.Position == stream.Length) { msg = TypeX.CreateInstance(type, null) as Message; } else { try { msg = reader.ReadObject(type) as Message; if (msg == null) { throw new XException("数据格式不正确!"); } } catch (Exception ex) { if (ignoreException) { stream.Position = start; return(null); } var em = ex.Message; if (DumpStreamWhenError) { stream.Position = start; var bin = String.Format("{0:yyyy_MM_dd_HHmmss_fff}.msg", DateTime.Now); bin = Path.Combine(XTrace.LogPath, bin); if (!Path.IsPathRooted(bin)) { bin = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, bin); } bin = Path.GetFullPath(bin); var dir = Path.GetDirectoryName(bin); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } File.WriteAllBytes(bin, stream.ReadBytes()); em = String.Format("已Dump数据流到{0}。{1}", bin, em); } var ex2 = new XException("无法从数据流中读取{0}(Kind={1})消息!{2}", type.Name, kind, em); throw ex2; } } msg.Header = header; return(msg); #endregion }