void Write(MetaType metaType, Type actual, ProtoWriter dest, int recursionLevel) { if (metaType.Type != actual) { foreach (var subType in metaType.GetSubtypes().OrderBy(st => st.FieldNumber)) { MetaType derivedType = subType.DerivedType; if (derivedType.Type == metaType.Type) { continue; } if (Helpers.IsAssignableFrom(derivedType.Type, actual)) { if (recursionLevel == 0) { if (derivedType.Type == actual) { ProtoWriter.WriteFieldHeaderComplete(WireType.Variant, dest); ProtoWriter.WriteInt32(subType.FieldNumber + 1, dest); return; } var token = ProtoWriter.StartSubItem(null, true, dest); ProtoWriter.WriteFieldHeaderIgnored(WireType.Variant, dest); ProtoWriter.WriteInt32(subType.FieldNumber + 1, dest); Write(derivedType, actual, dest, 1); ProtoWriter.EndSubItem(token, dest); } else { ProtoWriter.WriteFieldHeaderIgnored(WireType.Variant, dest); ProtoWriter.WriteInt32(subType.FieldNumber + 1, dest); Write(derivedType, actual, dest, recursionLevel + 1); } return; } } } if (recursionLevel == 0) { ProtoWriter.WriteFieldHeaderComplete(WireType.Variant, dest); ProtoWriter.WriteInt32(0, dest); } }
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); }