int ReadArray(BinaryReader reader, Type type, out object obj, SerializeAsAttribute attr) { int size = 0; if (attr.Length < 0) { throw new SerializationException("Array need attribute Length or LengthField"); } Array ar = Array.CreateInstance(type.GetElementType(), attr.Length); SerializeAsAttribute elementAttr = new SerializeAsAttribute(); elementAttr.Encoding = attr.Encoding; elementAttr.Size = attr.ElementSize; for (int i = 0; i < attr.Length; i++) { object element; Type elementType = attr.FieldType == null?type.GetElementType() : attr.FieldType; size += ReadMember(reader, elementType, out element, elementAttr); ar.SetValue(element, i); } obj = ar; return(size); }
int WriteArray(BinaryWriter writer, Type type, object obj, SerializeAsAttribute attr) { int size = 0; Array ar = (Array)obj; if (ar.Rank > 1) { throw new SerializationException("Multidimensional array not supported (" + type + ")"); } if (attr.Length < 0) { throw new SerializationException("Array need attribute Length or LengthField"); } SerializeAsAttribute elementAttr = new SerializeAsAttribute(); elementAttr.Encoding = attr.Encoding; elementAttr.Size = attr.ElementSize; for (int i = 0; i < attr.Length; i++) { object element = i < ar.Length ? ar.GetValue(i) : null; Type elementType = type.GetElementType(); if ((element == null) && (elementAttr.Size < 0)) { throw new SerializationException("Null elements in array needs attribute ElementSize or ElementSizeField"); } size += WriteMember(writer, elementType, element, elementAttr); } return(size); }
int ReadObject(BinaryReader reader, Type type, ref object obj, SerializeAsAttribute attr) { int size = 0; if (type.BaseType != _TypeOfObject) { size += ReadObject(reader, type.BaseType, ref obj, attr); } MemberInfo[] membersInfo = FormatterServices.GetSerializableMembers(type, _Contex); object[] membersData = new object[membersInfo.Length]; for (int i = 0; i < membersInfo.Length; i++) { MemberInfo memberInfo = membersInfo[i]; Debug.Assert(memberInfo is FieldInfo); SerializeAsAttribute memberAttr = GetSerializeAsAttribute(type, obj, memberInfo); object memberData; Type memberType = memberAttr.FieldType == null ? ((FieldInfo)memberInfo).FieldType : memberAttr.FieldType; size += ReadMember(reader, memberType, out memberData, memberAttr); membersData[i] = memberData; obj = FormatterServices.PopulateObjectMembers(obj, membersInfo, membersData); } return(size); }
int WriteObject(BinaryWriter writer, Type type, object obj, SerializeAsAttribute attr) { int size = 0; if (type.BaseType != _TypeOfObject) { size += WriteObject(writer, type.BaseType, obj, attr); } MemberInfo[] membersInfo = FormatterServices.GetSerializableMembers(type, _Contex); object[] membersData = FormatterServices.GetObjectData(obj, membersInfo); Debug.Assert(membersInfo.Length == membersData.Length); for (int i = 0; i < membersInfo.Length; i++) { MemberInfo memberInfo = membersInfo[i]; Debug.Assert(memberInfo is FieldInfo); object memberData = membersData[i]; Type memberType = memberData != null?memberData.GetType() : ((FieldInfo)memberInfo).FieldType; SerializeAsAttribute memberAttr = GetSerializeAsAttribute(type, obj, memberInfo); size += WriteMember(writer, memberType, memberData, memberAttr); } return(size); }
public CustomBinaryFormatter(SerializeAsAttribute defaultAttr) { _DefaultAttr = defaultAttr != null ? defaultAttr : new SerializeAsAttribute(); _Contex = new StreamingContext(StreamingContextStates.Clone | StreamingContextStates.File | StreamingContextStates.Persistence); if (_DefaultAttr.Encoding != "BCD") { _DefaultEncoding = Encoding.GetEncoding(_DefaultAttr.Encoding); } }
void Dispose(bool bDispose) { if (bDispose) { _Codes = null; _TypeOfObject = null; _TypeOfTimeSpan = null; _DefaultAttr = null; _NullData = null; _DefaultEncoding = null; } }
SerializeAsAttribute GetSerializeAsAttribute(Type parentType, object parentObject, MemberInfo member) { object[] customAttrs = member.GetCustomAttributes(typeof(SerializeAsAttribute), false); if (customAttrs.Length > 0) { Debug.Assert(customAttrs.Length == 1); SerializeAsAttribute attr = (SerializeAsAttribute)customAttrs[0]; attr.SetInfo(parentType, parentObject); return(attr); } return(_DefaultAttr); }
int WriteMember(BinaryWriter writer, Type type, object obj, SerializeAsAttribute attr) { int nullSize = 0; int size = 0; nullSize += WriteNullData(writer, attr.Offset); if (attr.Size == 0) { return(nullSize); } if (obj != null) { EValueType code = _Codes[(int)Type.GetTypeCode(type)]; if ((code != EValueType.Invalid) || (type == _TypeOfTimeSpan)) { size += WriteValue(writer, code, obj, attr); } else if (type.IsArray) { size += WriteArray(writer, type, obj, attr); } else { size += WriteObject(writer, type, obj, attr); } } if (attr.Size >= 0) { if (size > attr.Size) { throw new SerializationException("Object (= " + type + ") size (= " + size + ") rise specified attribute size (=" + attr.Size + ")"); } nullSize += WriteNullData(writer, attr.Size - size); } return(nullSize + size); }
int ReadMember(BinaryReader reader, Type type, out object obj, SerializeAsAttribute attr) { int nullSize = 0; int size = 0; nullSize += ReadNullData(reader, attr.Offset); obj = null; if (attr.Size == 0) { return(nullSize); } EValueType code = _Codes[(int)Type.GetTypeCode(type)]; if ((code != EValueType.Invalid) || (type == _TypeOfTimeSpan)) { size += ReadValue(reader, code, out obj, attr); } else if (type.IsArray) { size += ReadArray(reader, type, out obj, attr); } else { obj = FormatterServices.GetUninitializedObject(attr.FieldType == null ? type : attr.FieldType); size += ReadObject(reader, type, ref obj, attr); } if (attr.Size >= 0) { if (size > attr.Size) { throw new SerializationException("Object (= " + type + ") size (= " + size + ") rise specified attribute size (=" + attr.Size + ")"); } nullSize += ReadNullData(reader, attr.Size - size); } return(nullSize + size); }
int ReadValue(BinaryReader reader, EValueType code, out object obj, SerializeAsAttribute attr) { int size = 0; switch (code) { case EValueType.Boolean: obj = reader.ReadBoolean(); size = 1; break; case EValueType.Byte: obj = reader.ReadByte(); size = 1; break; case EValueType.SByte: obj = reader.ReadSByte(); size = 1; break; case EValueType.Int16: if (attr.NetEndian) { byte[] data = reader.ReadBytes(2); Array.Reverse(data); obj = BitConverter.ToInt16(data, 0); } else { obj = reader.ReadInt16(); } size = 2; break; case EValueType.UInt16: if (attr.NetEndian) { byte[] data = reader.ReadBytes(2); Array.Reverse(data); obj = BitConverter.ToUInt16(data, 0); } else { obj = reader.ReadUInt16(); } size = 2; break; case EValueType.Int32: if (attr.NetEndian) { byte[] data = reader.ReadBytes(4); Array.Reverse(data); obj = BitConverter.ToInt32(data, 0); } else { obj = reader.ReadInt32(); } size = 4; break; case EValueType.UInt32: if (attr.NetEndian) { byte[] data = reader.ReadBytes(4); Array.Reverse(data); obj = BitConverter.ToUInt32(data, 0); } else { obj = reader.ReadUInt32(); } size = 4; break; case EValueType.Int64: if (attr.NetEndian) { byte[] data = reader.ReadBytes(8); Array.Reverse(data); obj = BitConverter.ToInt64(data, 0); } else { obj = reader.ReadInt64(); } size = 8; break; case EValueType.UInt64: if (attr.NetEndian) { byte[] data = reader.ReadBytes(8); Array.Reverse(data); obj = BitConverter.ToUInt64(data, 0); } else { obj = reader.ReadUInt64(); } size = 8; break; case EValueType.Single: obj = reader.ReadSingle(); break; case EValueType.Double: obj = reader.ReadDouble(); break; case EValueType.String: if (attr.Encoding == "BCD") { byte len = reader.ReadByte(); byte[] data = reader.ReadBytes((len + 1) / 2); StringBuilder str = new StringBuilder(len); for (int i = 0, j = 0; i < len; i += 2, j++) { str.Append((char)((data[j] >> 4) + 0x30)); if (i < len - 1) { str.Append((char)((data[j] & 0x0F) + 0x30)); } } obj = str.ToString(); size = 1 + ((len + 1) / 2); } else { Encoding sEnc = attr.Encoding != _DefaultAttr.Encoding ? Encoding.GetEncoding(attr.Encoding) : _DefaultEncoding; if (attr.Size > 0) { byte[] data = reader.ReadBytes(attr.Size); int len = Array.IndexOf(data, (byte)0); obj = sEnc.GetString(data, 0, len >= 0 ? len : data.Length); if (obj == null) { obj = ""; } size = attr.Size; } else { byte[] data = new byte[0]; byte ch; do { ch = reader.ReadByte(); Array.Resize(ref data, data.Length + 1); data[data.Length - 1] = ch; } while (ch != 0); obj = sEnc.GetString(data); size = data.Length; } } break; default: throw new SerializationException("Not supported codeType (" + code + ")"); } return(size); }
int WriteValue(BinaryWriter writer, EValueType code, object obj, SerializeAsAttribute attr) { byte[] data = null; switch (code) { case EValueType.Boolean: data = BitConverter.GetBytes((bool)obj); break; case EValueType.Byte: case EValueType.SByte: data = new byte[1]; data[0] = (byte)obj; break; case EValueType.Int16: data = BitConverter.GetBytes((short)obj); if (attr.NetEndian) { Array.Reverse(data); } ; break; case EValueType.UInt16: data = BitConverter.GetBytes((ushort)obj); if (attr.NetEndian) { Array.Reverse(data); } ; break; case EValueType.Int32: data = BitConverter.GetBytes((int)obj); if (attr.NetEndian) { Array.Reverse(data); } ; break; case EValueType.UInt32: data = BitConverter.GetBytes((uint)obj); if (attr.NetEndian) { Array.Reverse(data); } ; break; case EValueType.Int64: data = BitConverter.GetBytes((long)obj); if (attr.NetEndian) { Array.Reverse(data); } ; break; case EValueType.UInt64: data = BitConverter.GetBytes((ulong)obj); if (attr.NetEndian) { Array.Reverse(data); } ; break; case EValueType.Single: data = BitConverter.GetBytes((float)obj); break; case EValueType.Double: data = BitConverter.GetBytes((double)obj); break; case EValueType.String: if (attr.Encoding == "BCD") { string str = ((string)obj).TrimEnd(' '); data = new byte[1 + ((str.Length + 1) / 2)]; data[0] = (byte)str.Length; for (int i = 0, pos = 1; i < str.Length; i++, pos++) { data[pos] = (byte)(((byte)str[i] - 0x30) * 16); if (i < str.Length - 1) { data[pos] += (byte)((byte)str[++i] - 0x30); } } } else { Encoding sEnc = attr.Encoding != _DefaultAttr.Encoding ? Encoding.GetEncoding(attr.Encoding) : _DefaultEncoding; data = sEnc.GetBytes((string)obj); if (attr.Size < 0) { Array.Resize(ref data, data.Length + 1); } } break; default: throw new SerializationException("Not supported codeType (" + code + ")"); } writer.Write(data, 0, data.Length); return(data.Length); }