public void SetLegacyFormat(ref MemberLevelSettingsValue level, MemberInfo member, RuntimeTypeModel model) { Type type = Helpers.GetMemberType(member); ValueFormat legacyFormat = ValueSerializerBuilder.GetDefaultLegacyFormat(type, model); switch (Helpers.GetTypeCode(type)) { // these can't be registered and don't have AsReferenceDefault // explicitely set their asReference = false case ProtoTypeCode.String: case ProtoTypeCode.ByteArray: case ProtoTypeCode.Type: case ProtoTypeCode.Uri: level.Format = legacyFormat; break; default: if (!RuntimeTypeModel.CheckTypeCanBeAdded(model, type)) { // for primitive types - explicitly level.Format = legacyFormat; } break; } }
// no need for special handling of !Nullable.HasValue - when boxing they will be applied NetObjectValueDecorator(Type type, bool asReference, bool asLateReference, bool allowNullWireType, RuntimeTypeModel model) { if (type == null) { throw new ArgumentNullException(nameof(type)); } _allowNullWireType = allowNullWireType; _options = BclHelpers.NetObjectOptions.UseConstructor; if (asReference) { _options |= BclHelpers.NetObjectOptions.AsReference; if (asLateReference) { _options |= BclHelpers.NetObjectOptions.WriteAsLateReference; } } else if (asLateReference) { throw new ArgumentException("Can't serialize as late reference when asReference = false", nameof(asReference)); } int baseKey = model.GetKey(type, false, true); int key = model.GetKey(type, false, false); if (!Helpers.IsValueType(type) && key >= 0 && baseKey >= 0 && ValueSerializerBuilder.CanTypeBeAsLateReferenceOnBuildStage(key, model, true)) { _lateReferenceTail = new LateReferenceSerializer(type, key, baseKey, model); } else if (asLateReference) { throw new ArgumentException("Can't use late reference with non-model or value type " + type.Name); } ProtoTypeCode typeCode = Helpers.GetTypeCode(type); // mind that this is set not for AsReference only // because AsReference may be switched in another version if (typeCode == ProtoTypeCode.String || typeCode == ProtoTypeCode.Type || typeCode == ProtoTypeCode.Uri) { _options |= BclHelpers.NetObjectOptions.LateSet; } // if this type is nullable it's ok // we'll unwrap it // and for non emit it's already boxed as not nullable this.ExpectedType = type; }
public MemberHandlerResult TryRead(AttributeMap attribute, MemberState s, MemberInfo member, RuntimeTypeModel model) { if (s.Input.IsEnumValueMember) { return(MemberHandlerResult.NotFound); } var main = s.MainValue; try { MemberLevelSettingsValue level = s.SerializationSettings.GetSettingsCopy(0).Basic; level.DefaultsMode = MemberDefaultsMode.Legacy; if (main.Tag <= 0) { attribute.TryGetNotDefault("Tag", ref main.Tag); } if (string.IsNullOrEmpty(main.Name)) { attribute.TryGetNotEmpty("Name", ref main.Name); } if (!main.IsRequiredInSchema) { attribute.TryGetNotDefault("IsRequired", ref main.IsRequiredInSchema); } var type = Helpers.GetMemberType(member); BinaryDataFormat dataFormat = 0; attribute.TryGetNotDefault("DataFormat", ref dataFormat); level.ContentBinaryFormatHint = dataFormat; bool isPacked = false; attribute.TryGetNotDefault("IsPacked", ref isPacked); level.Collection.Format = isPacked ? CollectionFormat.Protobuf : (model.ProtoCompatibility.SuppressCollectionEnhancedFormat ? CollectionFormat.ProtobufNotPacked : CollectionFormat.NotSpecified ); bool overwriteList = false; attribute.TryGetNotDefault("OverwriteList", ref overwriteList); level.Collection.Append = !overwriteList; if (!level.WriteAsDynamicType.GetValueOrDefault()) { attribute.TryGetNotDefault("DynamicType", ref level.WriteAsDynamicType); } bool dynamicType = level.WriteAsDynamicType.GetValueOrDefault(); bool asRefHasValue = false; bool notAsReference = false; #if !FEAT_IKVM // IKVM can't access AsReferenceHasValue, but conveniently, AsReference will only be returned if set via ctor or property attribute.TryGetNotDefault("AsReferenceHasValue", ref asRefHasValue, publicOnly: false); if (asRefHasValue) #endif { bool value = false; asRefHasValue = attribute.TryGetNotDefault("AsReference", ref value); if (asRefHasValue) // if AsReference = true - use defaults { notAsReference = !value; } } if (!asRefHasValue) { if (level.Format == ValueFormat.NotSpecified) { SetLegacyFormat(ref level, member, model); } } else { level.Format = notAsReference ? ValueSerializerBuilder.GetDefaultLegacyFormat(type, model) : ValueFormat.Reference; } s.TagIsPinned = main.Tag > 0; var dl = s.SerializationSettings.DefaultLevel.GetValueOrDefault(new ValueSerializationSettings.LevelValue(level.MakeDefaultNestedLevelForLegacyMember())); if (isPacked) { dl.Basic.Format = ValueFormat.Compact; } if (dynamicType) { // apply dynamic type to items Type itemType = null; Type defaultType = null; MetaType.ResolveListTypes(model, Helpers.GetMemberType(s.Member), ref itemType, ref defaultType); if (itemType != null) { dl.Basic.WriteAsDynamicType = true; dl.Basic.Format = ValueFormat.Reference; if (level.Format == ValueFormat.Compact || level.Format == ValueFormat.MinimalEnhancement) { level.WriteAsDynamicType = false; } } } s.SerializationSettings.DefaultLevel = dl; s.SerializationSettings.SetSettings(level, 0); return(s.TagIsPinned ? MemberHandlerResult.Done : MemberHandlerResult.Partial); // note minAcceptFieldNumber only applies to non-proto } finally { s.MainValue = main; } }
protected override TypeAttributeHandlerResult TryMap(AttributeMap item, TypeState s, TypeArgsValue a, RuntimeTypeModel model) { var main = s.SettingsValue; if (a.HasFamily(MetaType.AttributeFamily.ProtoBuf)) { object tmp; if (item.TryGet("Name", out tmp)) { main.Name = (string)tmp; } if (Helpers.IsEnum(s.Type)) // note this is subtly different to AsEnum; want to do this even if [Flags] { #if !FEAT_IKVM // IKVM can't access EnumPassthruHasValue, but conveniently, InferTagFromName will only be returned if set via ctor or property if (item.TryGet("EnumPassthruHasValue", false, out tmp) && (bool)tmp) #endif { if (item.TryGet("EnumPassthru", out tmp)) { main.EnumPassthru = (bool)tmp; } } } else { if (item.TryGet("DataMemberOffset", out tmp)) { s.DataMemberOffset = (int)tmp; } #if !FEAT_IKVM // IKVM can't access InferTagFromNameHasValue, but conveniently, InferTagFromName will only be returned if set via ctor or property if (item.TryGet("InferTagFromNameHasValue", false, out tmp) && (bool)tmp) #endif { if (item.TryGet("InferTagFromName", out tmp)) { s.InferTagByName = (bool)tmp; } } if (item.TryGet("ImplicitFields", out tmp) && tmp != null) { s.ImplicitFields = (ImplicitFieldsMode)(int)tmp; // note that this uses the bizarre unboxing rules of enums/underlying-types } if (item.TryGet("SkipConstructor", out tmp)) { main.SkipConstructor = (bool)tmp; } if (item.TryGet("IgnoreListHandling", out tmp)) { main.IgnoreListHandling = (bool)tmp; } if (item.TryGet("AsReferenceDefault", out tmp)) { if ((bool)tmp) { main.Member.Format = ValueFormat.Reference; } else { main.Member.Format = ValueSerializerBuilder.GetDefaultLegacyFormat(s.Type, model); } } if (item.TryGet("ImplicitFirstTag", out tmp) && (int)tmp > 0) { s.ImplicitFirstTag = (int)tmp; } if (item.TryGet("ConstructType", out tmp)) { main.ConstructType = (Type)tmp; } } s.SettingsValue = main; return(TypeAttributeHandlerResult.Done); } return(TypeAttributeHandlerResult.Continue); }