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;
            }
        }
Пример #2
0
        // 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;
            }
        }
Пример #4
0
        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);
        }