/// <summary> /// 构造 /// </summary> /// <param name="context"></param> public ProtocolDeserializingEventArgs(ReadContext context) { Context = context; }
/// <summary> /// 反序列化后触发 /// </summary> /// <param name="context"></param> protected virtual void OnDeserialized(ReadContext context) { // 事件由外部动态指定,拥有优先处理权 if (Deserialized != null) Deserialized(this, new ProtocolDeserializedEventArgs(context)); IProtocolSerializable custom = context.GetCustomInterface(); if (custom != null) custom.OnDeserialized(context); }
/// <summary> /// 为指定类型创建实例时触发 /// </summary> /// <remarks>当内部自定义后外部事件同时存在时,优先外部事件</remarks> /// <param name="context"></param> /// <param name="type"></param> /// <returns></returns> protected virtual Object OnCreateInstance(ReadContext context, Type type) { Object obj = null; if (CreateInstance != null) { ProtocolCreateInstanceEventArgs e = new ProtocolCreateInstanceEventArgs(); e.Context = context; e.Type = type; CreateInstance(this, e); obj = e.Obj; } if (obj == null) { IProtocolSerializable custom = context.GetCustomInterface(); if (custom != null) obj = custom.OnCreateInstance(context, type); } return obj; }
/// <summary> /// 从指定流读取数据填充到指定对象 /// </summary> /// <param name="stream"></param> /// <param name="obj"></param> /// <returns></returns> public Object Deserialize(Stream stream, Object obj) { ReadContext context = new ReadContext(); context.Formatter = this; context.Reader = new BinaryReaderX(stream); // 树,用于记录分析所到达的位置 context.Node = new ProtocolTreeNode(null, null); context.Node.Context = context; Type type = null; if (obj != null) type = obj.GetType(); //context.Config = FormatterConfig.Default; context.Config = Head.Config; // 使用默认设置读取头部 if (!Head.Config.NoHead) { ReadMember(context.Clone(Head, Head.GetType(), null, "Head") as ReadContext); OnDeserialized(context); //// 只有使用了头部,才使用头部设置信息,否则使用默认设置信息,因为远端需要正确识别数据 //context.Config = Head.Config; } if (type == null) { // 读取类名 Assembly asm = Assembly.Load(Head.AssemblyName); if (asm == null) throw new Exception("无法找到程序集" + Head.AssemblyName + "!"); type = asm.GetType(Head.TypeName); if (type == null) throw new Exception("无法找到类" + Head.TypeName + "!"); } context.Type = type; context.Node.Type = type; if (obj == null) obj = Activator.CreateInstance(type); context.Data = obj; ReadMember(context.Clone(obj, type, null, "Body") as ReadContext); OnDeserialized(context); return obj; }
/// <summary> /// 反序列化前触发 /// </summary> /// <param name="context"></param> /// <returns>是否允许反序列化当前字段或属性</returns> protected virtual Boolean OnDeserializing(ReadContext context) { Boolean b = true; // 事件由外部动态指定,拥有优先处理权 if (Deserializing != null) { ProtocolDeserializingEventArgs e = new ProtocolDeserializingEventArgs(context); e.Cancel = false; Deserializing(this, e); b = !e.Cancel; } IProtocolSerializable custom = context.GetCustomInterface(); if (custom != null) b = custom.OnDeserializing(context); return b; }
Array ReadArray(ReadContext context, Type elementType, Int32 n) { Array arr = Array.CreateInstance(elementType, n); for (int i = 0; i < n; i++) { Object obj = ReadMember(context.Clone(null, elementType, elementType, i.ToString()) as ReadContext); arr.SetValue(obj, i); OnDeserialized(context); } return arr; }
Object ReadEnumerable(ReadContext context) { Int32 n = context.Config.Size; if (n <= 0) n = context.Reader.ReadEncodedInt32(); if (n <= 0) return null; Type elementType = context.Type; if (context.Type.HasElementType) elementType = context.Type.GetElementType(); else if (context.Type.IsGenericType) { Type[] ts = context.Type.GetGenericArguments(); if (ts != null && ts.Length > 0) elementType = ts[0]; } Array arr = ReadArray(context, elementType, n); if (arr == null) return null; context.Data = Activator.CreateInstance(context.Type, arr); return context.Data; }
Object ReadObjectRef(ReadContext context) { if (!context.Config.UseRefObject) { // 不使用引用对象的时候,这里就需要判断了 if (context.Node.Depth > 1 && !context.Config.NotNull) { // 读取一个字节,探测是否为空 Byte b = context.Reader.ReadByte(); if (b == 0) { //context.Data = null; return null; } } } // 创建 if (context.Data == null) { context.Data = OnCreateInstance(context, context.Type); if (context.Data == null) context.Data = Activator.CreateInstance(context.Type); } // 添加对象到对象集合 if (context.Config.UseRefObject) context.Objects.Add(context.Data); // 先获取类特性,后获取成员特性,所以,成员特性优先于类特性 context.Config = context.Config.CloneAndMerge(context.Type); MemberInfo[] mis = FindAllSerialized(context.Type, context.Config.SerialProperty); if (mis != null && mis.Length > 0) { foreach (MemberInfo item in mis) { Object obj = null; if (item is FieldInfo) { FieldInfo fi = item as FieldInfo; FieldInfoX fix = fi; // 只有Object类型才计算值 if (Type.GetTypeCode(fi.FieldType) == TypeCode.Object) obj = fix.GetValue(context.Data); obj = ReadMember(context.Clone(obj, fi.FieldType, item) as ReadContext); fix.SetValue(context.Data, obj); OnDeserialized(context); } else { PropertyInfo pi = item as PropertyInfo; PropertyInfoX pix = pi; // 只有Object类型才计算值 if (Type.GetTypeCode(pi.PropertyType) == TypeCode.Object) obj = pix.GetValue(context.Data); obj = ReadMember(context.Clone(obj, pi.PropertyType, item) as ReadContext); if (pi.GetSetMethod() != null) pix.SetValue(context.Data, obj); OnDeserialized(context); } } } return context.Data; }
Object ReadArray(ReadContext context) { Int32 n = context.Config.Size; if (n <= 0) n = context.Reader.ReadEncodedInt32(); if (n <= 0) return null; // 特殊处理字节数组 if (context.Type == typeof(Byte[])) return context.Reader.ReadBytes(n); Type elementType = context.Type.GetElementType(); return ReadArray(context, elementType, n); }
private Object ReadMemberInternal(ReadContext context) { BinaryReaderX reader = context.Reader; Boolean encodeInt = context.Config.EncodeInt; // 基础类型 Object data = null; if (reader.TryReadValue(context.Type, encodeInt, out data)) { context.Data = data; return data; } #region 数组、枚举、值类型、对象 if (context.Config.UseRefObject) { // 对于非基本类型,先写入对象引用计数 if (context.Node.Depth > 1 && !context.Config.NotNull) { Int32 n = reader.ReadEncodedInt32(); // 计数0表示是空对象 if (n == 0) { context.Data = null; return null; } // 从对象集合中找到对象,无效反序列化 if (n <= context.Objects.Count) { context.Data = context.Objects[n - 1]; return context.Data; } //else if (n == context.Objects.Count + 1) //{ // // 该对象的第一个引用 //} //else // throw new InvalidOperationException("数据异常,从对象集合中找到对象!"); } } if (context.Type.IsArray) { return ReadArray(context); } else if (context.Data is IEnumerable || typeof(IEnumerable).IsAssignableFrom(context.Type)) { return ReadEnumerable(context); } else if (context.Type.IsValueType) { //if (context.Type == typeof(Guid)) return new Guid(reader.ReadBytes(16)); return ReadObjectRef(context); } else { if (context.Type == typeof(IPAddress)) { Int32 p = 0; if (!encodeInt) p = reader.ReadInt32(); else p = reader.ReadEncodedInt32(); //if (p <= -1) p = (Int64)(UInt32)p; //context.Data = new IPAddress(p); Byte[] buffer = reader.ReadBytes(p); context.Data = new IPAddress(buffer); return context.Data; } return ReadObjectRef(context); } #endregion }
/// <summary> /// 读取对象 /// </summary> /// <remarks> /// 非对象类型直接返回数据; /// 对象类型且参数context.Data不为空时,填充context.Data; /// 对象类型且参数context.Data为空时,创建对象,填充后返回 /// </remarks> /// <remarks> /// 分为几种情况: /// 1,空引用直接写入0 /// 2,基本值类型直接写入值 /// 3,非基本值类型先查找是否已有引用,已有则写入引用计数(从1开始,因为0表示空引用),没有则添加到引用集合,再写入引用计数 /// 4,数组和枚举类型先写入元素个数,再依次写入元素 /// 5,对象类型,反射得到属性和字段,一个个写入 /// 值得注意的是,数据和枚举本也使用引用计数防止重复引用,同时包含引用计数和元素个数 /// </remarks> /// <param name="context"></param> /// <returns></returns> public Object ReadMember(ReadContext context) { //WriteLog(context.Node.ToString()); if (!OnDeserializing(context)) return context.Data; Stream stream = context.Reader.BaseStream; Int64 pos = stream.Position; Object data = ReadMemberInternal(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("-", " ")); } return data; }
object IProtocolSerializable.OnCreateInstance(ReadContext context, Type type) { if (type == typeof(IPEndPoint)) return new IPEndPoint(IPAddress.Any, 0); return null; }
void IProtocolSerializable.OnDeserialized(ReadContext context) { }
bool IProtocolSerializable.OnDeserializing(ReadContext context) { return true; }