public object ReadValue(IStreamReader reader, ISerializeContext context, bool isReadTypeIdExpected) { context.Key = this.Name; context.ArrayIndex = null; if (isReadTypeIdExpected) { // read type of property uint actualTypeId = reader.ReadUInt32(); if (TypeId != actualTypeId) { if (actualTypeId == (int)ItemType.ComplexObject) { // Special read > only null expected byte contentObjType = reader.ReadUInt8(); if (contentObjType == ValueItem.NullValueIdent) { return(null); } else { throw new ArgumentException("ComplexObject type ID is only expected with null!"); } } var actualStructure = context.GetByTypeId(actualTypeId); if (actualStructure == null) { // type not in local cache > type meta info exptected actualStructure = TypeMetaStructure.ReadContentTypeMetaInfo(reader, actualTypeId, context); } if (actualStructure.IsTypePrefixExpected) { if (actualStructure is ITypePrefix) { // type id already consumed > do not read again return(((ITypePrefix)actualStructure).ReadValue(reader, context, false)); } else { return(actualStructure.ReadValue(reader, context)); } } else { // read content type because of unknown strucutre byte contentObjType = reader.ReadUInt8(); if (contentObjType == ValueItem.NullValueIdent) { return(null); } else { return(actualStructure.ReadValue(reader, context)); } } } } byte contentType = reader.ReadUInt8(); if (contentType == ValueItem.TypeMetaInfo) { // type meta data already loaded for type id > skip data TypeMetaStructure.SkipTypeMetaInfo(reader); contentType = reader.ReadUInt8(); } switch (contentType) { case ValueItem.SingleObjectIdent: object newObject = TypeService.CreateInstance(concreteTargetType); object oldParentObj = context.ParentObject; context.ParentObject = newObject; for (int itemIndex = 0; itemIndex < items.Count; itemIndex++) { var item = items[itemIndex]; var itemValue = item.ReadValue(reader, context); item.SetItemValue(newObject, itemValue); } context.ParentObject = oldParentObj; return(newObject); case ValueItem.NullValueIdent: return(null); case ValueItem.CollectionObjectIdent: throw new NotImplementedException(); default: throw new InvalidOperationException($"Type ident {contentType} not expected!"); } }
public object ReadValue(IStreamReader reader, ISerializeContext context) { byte contentType = reader.ReadUInt8(); context.Key = this.Name; if (contentType == ValueItem.CollectionObjectIdent) { int count = reader.ReadInt32(); if (isArray) { Array array = Array.CreateInstance(itemType, count); if (isByteArray) { return(reader.ReadBytes(count).ToArray()); } else { for (int i = 0; i < count; i++) { context.ArrayIndex = i; var item = itemStructure.ReadValue(reader, context); array.SetValue(item, i); } context.ArrayIndex = null; } return(array); } else if (implementsIList) { IList coll = (IList)TypeService.CreateInstance(targetCollectionType); for (int i = 0; i < count; i++) { context.ArrayIndex = i; var item = itemStructure.ReadValue(reader, context); coll.Add(item); } context.ArrayIndex = null; return(coll); } else { object specialColl = TypeService.CreateInstance(targetCollectionType); for (int i = 0; i < count; i++) { context.ArrayIndex = i; var item = itemStructure.ReadValue(reader, context); specialCollAddMethod.Invoke(specialColl, new object[] { item }); } context.ArrayIndex = null; return(specialColl); } } else if (contentType == ValueItem.NullValueIdent) { return(null); } else if (contentType == ValueItem.TypeMetaInfo) { TypeMetaStructure.SkipTypeMetaInfo(reader); return(this.ReadValue(reader, context)); } else { throw new InvalidOperationException($"Type ident {contentType} not expected!"); } }
public void WriteValue(IStreamWriter writer, ISerializeContext context, object value) { // Complex structure // TypeID UInt32 // ContentType Byte context.Key = this.Name; if (isObject) { // property or collection does not specify a target type // determine object type if (value != null) { Type valType = value.GetType(); IValueItem item; var differentTargetStructure = context.DetermineSpecialInterfaceType(value.GetType(), type); if (differentTargetStructure != null) { item = differentTargetStructure; } else { item = context.GetByType(valType); } if (!item.IsTypePrefixExpected) { // Write type id for value types as well (unknown structure) writer.WriteUInt32(item.TypeId); writer.WriteUInt8(ValueItem.SingleValueIdent); } item.WriteValue(writer, context, value); } else { // write complex object type id for null value writer.WriteInt32((int)ItemType.ComplexObject); writer.WriteUInt8(ValueItem.NullValueIdent); } } else if (value == null) { // Write null writer.WriteUInt32(this.TypeId); writer.WriteUInt8(ValueItem.NullValueIdent); } else { IValueItem differentTargetStructure = null; if (CheckDifferentType) { differentTargetStructure = context.DetermineSpecialInterfaceType(value.GetType(), type); } if (differentTargetStructure != null) { // Special target interface type serialization differentTargetStructure.WriteValue(writer, context, value); } else { // Just write type properties writer.WriteUInt32(this.TypeId); if (context.IsWriteTypeMetaInfoRequired(this.TypeId)) { // serialize type meta info at the first time TypeMetaStructure.WriteTypeMetaInfo(writer, this); } writer.WriteUInt8(ValueItem.SingleObjectIdent); object oldParentObj = context.ParentObject; context.ParentObject = value; for (int itemIndex = 0; itemIndex < items.Count; itemIndex++) { var item = items[itemIndex]; var valueItem = item.GetItemValue(value); item.WriteValue(writer, context, valueItem); } context.ParentObject = oldParentObj; } } }
public void WriteValue(IStreamWriter writer, ISerializeContext context, object value) { // Collection structure: // TypeID UInt32 // ContentType Byte // Count Int32 // Items... if (getter == null) { writer.WriteUInt32(this.TypeId); // only write collection type if element is root object if (context.IsWriteTypeMetaInfoRequired(this.TypeId)) { // serialize type meta info at the first time TypeMetaStructure.WriteTypeMetaInfo(writer, this); } } if (value == null) { writer.WriteUInt8(ValueItem.NullValueIdent); } else { writer.WriteUInt8(ValueItem.CollectionObjectIdent); IEnumerable items; if (isArray) { Array array = (Array)value; writer.WriteInt32(array.Length); items = array; if (isByteArray) { writer.WriteBytes(new ArraySegment <byte>((byte[])array)); return; } } else if (value is ICollection) { ICollection collection = (ICollection)value; writer.WriteInt32(collection.Count); items = collection; } else { items = (IEnumerable)value; int count = 0; foreach (var item in items) { count++; } writer.WriteInt32(count); } context.Key = this.Name; int index = 0; foreach (var item in items) { context.ArrayIndex = index; itemStructure.WriteValue(writer, context, item); index++; } context.ArrayIndex = null; } }