示例#1
0
        public virtual void ApplyDefaultBehaviour(MetaType metaType)
        {
            var  type     = metaType.Type;
            Type baseType = metaType.GetBaseType();

            if (baseType != null &&
                CanAutoAddType(baseType) &&
                MetaType.CanHaveSubType(baseType))
            {
                Model.FindOrAddAuto(baseType, true, false, false);
            }

            try
            {
                AttributeFamily family;
                TypeState       mapped;

                {
                    AttributeMap[] typeAttribs = AttributeMap.Create(Model, type, false);
                    family = GetContractFamily(type, typeAttribs);

                    mapped = TypeMapper.Map(
                        new TypeArgsValue(type, typeAttribs, AcceptableAttributes, Model)
                    {
                        Family = family,
                        ImplicitFallbackMode = ImplicitFallbackMode,
                    });

                    foreach (var candidate in mapped.DerivedTypes)
                    {
                        if (metaType.IsValidSubType(candidate.Type))
                        {
                            metaType.AddSubType(candidate.Tag, candidate.Type);
                        }
                    }

                    metaType.ReplaceClientSettings(mapped.SettingsValue);
                }

                var  partialMembers             = mapped.PartialMembers;
                int  dataMemberOffset           = mapped.DataMemberOffset;
                int  implicitFirstTag           = mapped.ImplicitFirstTag;
                bool inferTagByName             = mapped.InferTagByName;
                ImplicitFieldsMode implicitMode = mapped.ImplicitFields;
                family = mapped.Input.Family;

                MethodInfo[] callbacks = null;

                var members = new List <MappedMember>();

                bool isEnum = Helpers.IsEnum(type);
#if WINRT
                System.Collections.Generic.IEnumerable <MemberInfo> foundList;
                if (isEnum)
                {
                    foundList = type.GetRuntimeFields().Where(x => x.IsStatic && x.IsPublic);
                }
                else
                {
                    System.Collections.Generic.List <MemberInfo> list = new System.Collections.Generic.List <MemberInfo>();
                    foreach (PropertyInfo prop in type.GetRuntimeProperties())
                    {
                        MethodInfo getter = Helpers.GetGetMethod(prop, false, false);
                        if (getter != null && !getter.IsStatic)
                        {
                            list.Add(prop);
                        }
                    }
                    foreach (FieldInfo fld in type.GetRuntimeFields())
                    {
                        if (fld.IsPublic && !fld.IsStatic)
                        {
                            list.Add(fld);
                        }
                    }
                    foreach (MethodInfo mthd in type.GetRuntimeMethods())
                    {
                        if (mthd.IsPublic && !mthd.IsStatic)
                        {
                            list.Add(mthd);
                        }
                    }
                    foundList = list;
                }
#else
                MemberInfo[] foundList = type.GetMembers(isEnum
                    ? BindingFlags.Public | BindingFlags.Static
                    : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                if (isEnum)
                {
                    foundList = foundList.Where(x => x is FieldInfo).ToArray();
                }
#endif
                foreach (MemberInfo member in foundList)
                {
                    if (member.DeclaringType != type)
                    {
                        continue;
                    }
                    var map = AttributeMap.Create(Model, member, true);

                    {
                        var args = new MemberArgsValue(member, map, AcceptableAttributes, Model)
                        {
                            DataMemberOffset  = dataMemberOffset,
                            Family            = family,
                            InferTagByName    = inferTagByName,
                            PartialMembers    = partialMembers,
                            IsEnumValueMember = isEnum
                        };

                        PropertyInfo property;
                        FieldInfo    field;
                        if ((property = member as PropertyInfo) != null)
                        {
                            bool isPublic = Helpers.GetGetMethod(property, false, false) != null;

                            bool canBeMapped = isPublic || Helpers.GetGetMethod(property, true, true) != null;

                            if (canBeMapped &&
                                (!mapped.ImplicitOnlyWriteable ||
                                 Helpers.CheckIfPropertyWritable
                                 (
                                     Model,
                                     property,
                                     implicitMode == ImplicitFieldsMode.AllProperties || implicitMode == ImplicitFieldsMode.AllFieldsAndProperties,
                                     false)))
                            {
                                switch (implicitMode)
                                {
                                case ImplicitFieldsMode.AllProperties:
                                    args.IsForced = true;
                                    break;

                                case ImplicitFieldsMode.PublicProperties:
                                    if (isPublic)
                                    {
                                        args.IsForced = true;
                                    }
                                    break;

                                case ImplicitFieldsMode.PublicFieldsAndProperties:
                                    if (isPublic)
                                    {
                                        args.IsForced = true;
                                    }
                                    break;

                                case ImplicitFieldsMode.AllFieldsAndProperties:
                                    args.IsForced = true;
                                    break;
                                }
                            }

                            var r = ApplyDefaultBehaviour_AddMembers(args);
                            if (r != null)
                            {
                                if (!canBeMapped)
                                {
                                    throw new MemberAccessException("Property " + property + " should be readable to be mapped.");
                                }
                                members.Add(r);
                            }
                        }
                        else if ((field = member as FieldInfo) != null)
                        {
                            bool isPublic = field.IsPublic;

                            if (!args.IsEnumValueMember)
                            {
                                switch (implicitMode)
                                {
                                case ImplicitFieldsMode.AllFields:
                                    args.IsForced = true;
                                    break;

                                case ImplicitFieldsMode.PublicFields:
                                    if (isPublic)
                                    {
                                        args.IsForced = true;
                                    }
                                    break;

                                case ImplicitFieldsMode.PublicFieldsAndProperties:
                                    if (isPublic)
                                    {
                                        args.IsForced = true;
                                    }
                                    break;

                                case ImplicitFieldsMode.AllFieldsAndProperties:
                                    args.IsForced = true;
                                    break;
                                }
                            }

                            var r = ApplyDefaultBehaviour_AddMembers(args);
                            if (r != null)
                            {
                                members.Add(r);
                            }
                        }
                    }

                    MethodInfo method;
                    if ((method = member as MethodInfo) != null)
                    {
                        AttributeMap[] memberAttribs = AttributeMap.Create(Model, method, false);
                        if (memberAttribs != null && memberAttribs.Length > 0)
                        {
                            const int max = 11;
                            if (CanUse(AttributeType.ProtoBuf))
                            {
                                CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0, max);
                                CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1, max);
                                CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2, max);
                                CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3, max);
                            }

                            CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4, max);
                            CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5, max);
                            CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6, max);
                            CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7, max);

                            if (CanUse(AttributeType.Aqla))
                            {
                                CheckForCallback(method, memberAttribs, "AqlaSerializer.BeforeSerializationCallbackAttribute", ref callbacks, 8, max);
                                CheckForCallback(method, memberAttribs, "AqlaSerializer.AfterSerializationCallbackAttribute", ref callbacks, 9, max);
                                CheckForCallback(method, memberAttribs, "AqlaSerializer.BeforeDeserializationCallbackAttribute", ref callbacks, 10, max);
                                CheckForCallback(method, memberAttribs, "AqlaSerializer.AfterDeserializationCallbackAttribute", ref callbacks, 11, max);
                            }
                        }
                    }
                }
                if (inferTagByName || implicitMode != ImplicitFieldsMode.None)
                {
                    members.Sort();
                    foreach (var member in members)
                    {
                        if (!member.MappingState.TagIsPinned) // if ProtoMember etc sets a tag, we'll trust it
                        {
                            member.Tag = -1;
                        }
                    }
                }

                foreach (var member in members.OrderBy(m => m.MappingState.TagIsPinned ? 0 : 1))
                {
                    ApplyDefaultBehaviour(metaType, member,
                                          (inferTagByName || implicitMode != ImplicitFieldsMode.None) ? (int?)implicitFirstTag : null);
                }

                if (callbacks != null)
                {
                    metaType.SetCallbacks(Coalesce(callbacks, 0, 4, 8), Coalesce(callbacks, 1, 5, 9),
                                          Coalesce(callbacks, 2, 6, 10), Coalesce(callbacks, 3, 7, 11));
                }

                if (!DisableAutoAddingMemberTypes)
                {
                    foreach (var member in members)
                    {
                        if (!member.MappingState.Input.IsEnumValueMember)
                        {
                            Type memberType = Helpers.GetMemberType(member.Member);
                            memberType = Helpers.GetNullableUnderlyingType(memberType) ?? memberType;
                            if (memberType.IsArray)
                            {
                                memberType = memberType.GetElementType();
                            }
                            memberType = TypeModel.GetListItemType(Model, memberType) ?? memberType;
                            if (memberType == null)
                            {
                                continue;
                            }

                            if (CanAutoAddType(memberType))
                            {
                                Model.FindOrAddAuto(memberType, true, false, false);
                            }
                        }
                    }
                }

                if (UseLegacyTupleFields)
                {
                    foreach (ValueMember vm in metaType.GetTupleFields())
                    {
                        vm.SetSettings(x => x.V.DefaultsMode = MemberDefaultsMode.LegacyTuple);
                    }
                }
            }
            finally
            {
                if (baseType != null && GetContractFamily(baseType) != AttributeFamily.None)
                {
                    if (Model.FindWithoutAdd(baseType) != null)
                    {
                        MetaType baseMeta = Model[baseType];
                        // we can't add to frozen base type
                        // but this is not always an error
                        // e.g. dynamic member of base type doesn't need registered subtype
                        if (!baseMeta.IsFrozen && !DisableAutoRegisteringSubtypes && !baseMeta.IsList && baseMeta.IsValidSubType(type) && CanAutoAddType(baseType))
                        {
                            baseMeta.AddSubType(baseMeta.GetNextFreeFieldNumber(AutoRegisteringSubtypesFirstTag), type);
                        }
                    }
                }
            }
        }