public void Write(object value, ProtoWriter dest) { if (_allowNullWireType && value == null) { ProtoWriter.WriteFieldHeaderComplete(WireType.Null, dest); return; } bool write; int dynamicTypeKey; var options = _options; if ((options & BclHelpers.NetObjectOptions.WriteAsLateReference) != 0 && !ProtoWriter.CheckIsOnHalfToRecursionDepthLimit(dest)) { options &= ~BclHelpers.NetObjectOptions.WriteAsLateReference; } SubItemToken token = NetObjectHelpers.WriteNetObject_Start(value, dest, options, out dynamicTypeKey, out write); if (write) { // field header written! if ((options & BclHelpers.NetObjectOptions.DynamicType) != 0) { if (dynamicTypeKey < 0) { ProtoTypeCode typeCode = HelpersInternal.GetTypeCode(value.GetType()); WireType wireType = HelpersInternal.GetWireType(typeCode, _dataFormatForDynamicBuiltins); if (wireType != WireType.None) { ProtoWriter.WriteFieldHeaderComplete(wireType, dest); if (!ProtoWriter.TryWriteBuiltinTypeValue(value, typeCode, true, dest)) { throw new ProtoException("Dynamic type is not a contract-type: " + value.GetType().Name); } } else { throw new ProtoException("Dynamic type is not a contract-type: " + value.GetType().Name); } } else { ProtoWriter.WriteRecursionSafeObject(value, dynamicTypeKey, dest); } } else { if ((options & BclHelpers.NetObjectOptions.WriteAsLateReference) != 0) { _lateReferenceTail.Write(value, dest); } else if (_tail != null) { _tail.Write(value, dest); } else { Debug.Assert(_baseKey >= 0); if (_baseKeySerializer != null) { _baseKeySerializer.Write(value, dest); } else { ProtoWriter.WriteRecursionSafeObject(value, _baseKey, dest); } } } } ProtoWriter.EndSubItem(token, dest); }
public object Read(object value, ProtoReader source) { var type = ExpectedType; if (source.WireType == WireType.Null) { return(Helpers.IsValueType(type) ? Activator.CreateInstance(type) : null); } if (!RequiresOldValue) { value = null; } bool shouldEnd; int newTypeRefKey; int newObjectKey; int typeKey = _baseKey; bool isDynamic; bool isLateReference; BclHelpers.NetObjectOptions options = _options; SubItemToken token = NetObjectHelpers.ReadNetObject_Start( ref value, source, ref type, options, out isDynamic, out isLateReference, ref typeKey, out newObjectKey, out newTypeRefKey, out shouldEnd); if (shouldEnd) { object oldValue = value; if (typeKey >= 0) { // can be only for builtins options &= ~BclHelpers.NetObjectOptions.LateSet; if (typeKey == _baseKey && _baseKeySerializer != null) { if (isLateReference) { if (_lateReferenceTail == null) { throw new ProtoException("Late reference can't be deserialized for type " + ExpectedType.Name); } value = _lateReferenceTail.Read(value, source); } else { value = _baseKeySerializer.Read(value, source); } } else { Debug.Assert(isDynamic); value = ProtoReader.ReadObject(value, typeKey, source); } } else { if (isDynamic) { if (source.TryReadBuiltinType(ref value, Helpers.GetTypeCode(type), true)) { options |= BclHelpers.NetObjectOptions.LateSet; } else { throw new ProtoException("Dynamic type is not a contract-type: " + type.Name); } } else { if (isLateReference) { if (_lateReferenceTail == null) { throw new ProtoException("Late reference can't be deserialized for type " + ExpectedType.Name); } value = _lateReferenceTail.Read(value, source); } else { if (_tail == null) { throw new ProtoException("Dynamic type expected but no type info was read"); } else { // ensure consistent behavior with emit version value = _tail.Read(_tail.RequiresOldValue ? value : null, source); } } } } NetObjectHelpers.ReadNetObject_EndWithNoteNewObject(value, source, oldValue, type, newObjectKey, newTypeRefKey, options, token); } else { if (Helpers.IsValueType(ExpectedType) && value == null) { value = Activator.CreateInstance(ExpectedType); } ProtoReader.EndSubItem(token, source); } return(value); }