/// <summary> /// 序列化前触发 /// </summary> /// <param name="context"></param> /// <returns>是否允许序列化当前字段或属性</returns> protected virtual Boolean OnSerializing(WriteContext context) { Boolean b = true; // 事件由外部动态指定,拥有优先处理权 if (Serializing != null) { ProtocolSerializingEventArgs e = new ProtocolSerializingEventArgs(context); e.Cancel = false; Serializing(this, e); b = !e.Cancel; } IProtocolSerializable custom = context.GetCustomInterface(); if (custom != null) b = custom.OnSerializing(context); return b; }
/// <summary> /// 序列化后触发 /// </summary> /// <param name="context"></param> protected virtual void OnSerialized(WriteContext context) { // 事件由外部动态指定,拥有优先处理权 if (Serialized != null) Serialized(this, new ProtocolSerializedEventArgs(context)); IProtocolSerializable custom = context.GetCustomInterface(); if (custom != null) custom.OnSerialized(context); }
void WriteEnumerable(WriteContext context) { // 先写元素个数 IEnumerable arr = context.Data as IEnumerable; Int32 count = 0; foreach (Object item in arr) { count++; } // 特性指定了长度,这里就不需要再写入长度了 if (context.Config.Size <= 0) context.Writer.WriteEncoded(count); Int32 n = 0; foreach (Object item in arr) { Type type = null; if (item != null) type = item.GetType(); WriteMember(context.Clone(item, type, type, n++.ToString()) as WriteContext); } }
/// <summary> /// 把一个对象序列化到指定流中 /// </summary> /// <param name="stream"></param> /// <param name="obj"></param> public void Serialize(Stream stream, object obj) { if (obj == null) throw new ArgumentNullException("obj"); WriteContext context = new WriteContext(); context.Formatter = this; context.Writer = new BinaryWriterX(stream); context.Data = obj; context.Type = obj.GetType(); // 树,用于记录分析所到达的位置 context.Node = new ProtocolTreeNode(null, context.Type); context.Node.Context = context; //context.Config = FormatterConfig.Default; context.Config = Head.Config; //RefObjects = null; // 使用默认设置写入头部 if (!Head.Config.NoHead) { Head.AssemblyName = context.Type.Assembly.FullName; Head.TypeName = context.Type.FullName; //WriteMember(writer, Head, config, node.Add("Head", Head.GetType())); WriteMember(context.Clone(Head, Head.GetType(), null, "Head") as WriteContext); //// 只有使用了头部,才使用头部设置信息,否则使用默认设置信息,因为远端需要正确识别数据 //context.Config = Head.Config; } // 写入主体 //WriteMember(writer, obj, config, node.Add("Body", obj.GetType())); WriteMember(context.Clone(obj, context.Type, null, "Body") as WriteContext); }
void WriteObjectRef(WriteContext context) { //// 检测循环引用 //if (RefObjects == null) RefObjects = new Dictionary<Object, Int32>(); //if (RefObjects.ContainsKey(context.Data)) // throw new InvalidOperationException("检测到循环引用!" + context.Node); //RefObjects.Add(context.Data, RefObjects.Count + 1); // 写入一个字节表示当前对象不为空 // 实际上,还可以建立一个只能容纳255个类型的数组,这个字节用于表示类型 if (!context.Config.UseRefObject && context.Node.Depth > 1 && !context.Config.NotNull) context.Writer.Write((Byte)1); Type type = context.Type; // 对于对象引用型的字段,需要合并上类上的设置 context.Config = context.Config.CloneAndMerge(type); // 反射得到所有需要序列化的字段或属性 MemberInfo[] mis = FindAllSerialized(type, context.Config.SerialProperty); if (mis != null && mis.Length > 0) { // 先获取类特性,后获取成员特性,所以,成员特性优先于类特性 foreach (MemberInfo item in mis) { if (item is FieldInfo) { FieldInfo fi = item as FieldInfo; Object obj = FieldInfoX.Create(fi).GetValue(context.Data); type = obj == null ? fi.FieldType : obj.GetType(); WriteMember(context.Clone(obj, type, item) as WriteContext); } else { PropertyInfo pi = item as PropertyInfo; Object obj = PropertyInfoX.Create(pi).GetValue(context.Data); type = obj == null ? pi.PropertyType : obj.GetType(); WriteMember(context.Clone(obj, type, item) as WriteContext); } } } }
void WriteArray(WriteContext context) { // 先写元素个数 Array arr = context.Data as Array; // 特性指定了长度,这里就不需要再写入长度了 if (context.Config.Size <= 0) context.Writer.WriteEncoded(arr.Length); // 特殊处理字节数组 if (context.Type == typeof(Byte[])) { context.Writer.Write((Byte[])context.Data); return; } Int32 n = 0; foreach (Object item in arr) { Type type = null; if (item != null) type = item.GetType(); WriteMember(context.Clone(item, type, type, n++.ToString()) as WriteContext); } }
private void WriteMemberInternal(WriteContext context) { BinaryWriterX writer = context.Writer; Object data = context.Data; Boolean encodeInt = context.Config.EncodeInt; // 空数据时,写个0字节占位,如果配置为非空,则抛出异常 if (data == null) { if (context.Config.NotNull) throw new InvalidOperationException("在非空设置下遇到空节点!" + context.Node.Path); writer.Write((Byte)0); return; } // 基础类型 if (writer.WriteValue(data, encodeInt)) return; // 引用对象 if (context.Config.UseRefObject) { // 对于非基本类型,先写入对象引用计数 // 计数0表示是空对象 if (context.Node.Depth > 1 && !context.Config.NotNull) { Int32 n = context.Objects.IndexOf(data); if (n >= 0) { // 该对象已经写入,这里写入引用计数即可 writer.WriteEncoded(n + 1); return; } } context.Objects.Add(data); // 不写对象引用计数 if (context.Node.Depth > 1 && !context.Config.NotNull) writer.WriteEncoded(context.Objects.Count); } #region 数组、枚举、值类型、对象 if (context.Type.IsArray) { WriteArray(context); return; } if (data is IEnumerable) { WriteEnumerable(context); return; } //else { if (context.Type == typeof(IPAddress)) { IPAddress ip = data as IPAddress; Byte[] buffer = ip.GetAddressBytes(); if (!encodeInt) writer.Write(buffer.Length); else writer.WriteEncoded(buffer.Length); writer.Write(buffer); return; } WriteObjectRef(context); } #endregion }
/// <summary> /// 写入对象 /// </summary> /// <remarks> /// 分为几种情况: /// 1,空引用直接写入0 /// 2,基本值类型直接写入值 /// 3,非基本值类型先查找是否已有引用,已有则写入引用计数(从1开始,因为0表示空引用),没有则添加到引用集合,不写引用计数 /// 4,数组和枚举类型先写入元素个数,再依次写入元素 /// 5,对象类型,反射得到属性和字段,一个个写入 /// 值得注意的是,数据和枚举本也使用引用计数防止重复引用,同时包含引用计数和元素个数 /// </remarks> /// <param name="context"></param> public void WriteMember(WriteContext context) { //WriteLog(context.Node.ToString()); Stream stream = context.Writer.BaseStream; Int64 pos = stream.Position; if (OnSerializing(context)) { WriteMemberInternal(context); OnSerialized(context); } Int64 pos2 = stream.Position; if (pos2 > pos) { stream.Seek(pos, SeekOrigin.Begin); Byte[] buffer = new Byte[pos2 - pos]; stream.Read(buffer, 0, buffer.Length); WriteLog("{0} [{1}] {2}", context.Node.ToString(), buffer.Length, BitConverter.ToString(buffer).Replace("-", " ")); } }
void IProtocolSerializable.OnSerialized(WriteContext context) { }
bool IProtocolSerializable.OnSerializing(WriteContext context) { return true; }
/// <summary> /// 构造 /// </summary> /// <param name="context"></param> public ProtocolSerializingEventArgs(WriteContext context) { Context = context; }