示例#1
0
        /// <summary>
        /// Deserializes the members.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>The deserialized list of member values.</returns>
        protected virtual List <MemberValue> DeserializeMembers(ISerializationContext <TSerializationContext> context)
        {
            ApiCop.UpdateRule <InitializationApiCopRule>("SerializerBase.WarmupAtStartup",
                                                         x => x.SetInitializationMode(InitializationMode.Lazy, GetType().GetSafeFullName()));

            var deserializedMemberValues = new List <MemberValue>();

            var serializerModifiers = SerializationManager.GetSerializerModifiers(context.ModelType).Reverse();

            var membersToDeserialize = GetSerializableMembers(context.Model);

            foreach (var member in membersToDeserialize)
            {
                var memberSerializationEventArgs = new MemberSerializationEventArgs(context, member);

                DeserializingMember.SafeInvoke(this, memberSerializationEventArgs);

                BeforeDeserializeMember(context, member);

                var serializationObject = DeserializeMember(context, member);
                if (serializationObject.IsSuccessful)
                {
                    // Note that we need to sync the member values every time
                    var memberValue = new MemberValue(member.MemberGroup, member.ModelType, member.Type, member.Name, serializationObject.MemberValue);
                    member.Value = memberValue.Value;

                    deserializedMemberValues.Add(memberValue);

                    foreach (var serializerModifier in serializerModifiers)
                    {
                        serializerModifier.DeserializeMember(context, member);
                        memberValue.Value = member.Value;
                    }

                    AfterDeserializeMember(context, member);
                    memberValue.Value = member.Value;

                    DeserializedMember.SafeInvoke(this, memberSerializationEventArgs);
                    memberValue.Value = member.Value;
                }
            }

            if (deserializedMemberValues.Count > 0)
            {
                PopulateModel(context.Model, deserializedMemberValues.ToArray());
            }

            return(deserializedMemberValues);
        }
        /// <summary>
        /// Deserializes the members.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>The deserialized list of member values.</returns>
        protected virtual List <MemberValue> DeserializeMembers(ISerializationContext <TSerializationContext> context)
        {
            ApiCop.UpdateRule <InitializationApiCopRule>("SerializerBase.WarmupAtStartup",
                                                         x => x.SetInitializationMode(InitializationMode.Lazy, GetType().GetSafeFullName(false)));

            var deserializedMemberValues = new List <MemberValue>();

            var serializerModifiers = SerializationManager.GetSerializerModifiers(context.ModelType).Reverse();

            var membersToDeserialize = GetSerializableMembers(context, context.Model);

            foreach (var member in membersToDeserialize)
            {
                var memberSerializationEventArgs = new MemberSerializationEventArgs(context, member);

                DeserializingMember.SafeInvoke(this, memberSerializationEventArgs);

                BeforeDeserializeMember(context, member);

                var serializationObject = DeserializeMember(context, member);
                if (serializationObject.IsSuccessful)
                {
                    // Note that we need to sync the member values every time
                    var memberValue = new MemberValue(member.MemberGroup, member.ModelType, member.MemberType, member.Name,
                                                      member.NameForSerialization, serializationObject.MemberValue);

                    if (memberValue.MemberGroup == SerializationMemberGroup.Dictionary)
                    {
                        var targetDictionary = TypeFactory.CreateInstance(member.MemberType) as IDictionary;
                        if (targetDictionary == null)
                        {
                            throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a dictionary, but target model cannot be updated because it does not implement IDictionary",
                                                                                      context.ModelTypeName);
                        }

                        var enumerable = memberValue.Value as List <SerializableKeyValuePair>;
                        if (enumerable != null)
                        {
                            foreach (var item in enumerable)
                            {
                                targetDictionary.Add(item.Key, item.Value);
                            }
                        }
                        else
                        {
                            var sourceDictionary = memberValue.Value as IDictionary;
                            if (sourceDictionary != null)
                            {
                                foreach (var key in sourceDictionary.Keys)
                                {
                                    targetDictionary.Add(key, sourceDictionary[key]);
                                }
                            }
                        }

                        member.Value = targetDictionary;
                    }
                    else if (memberValue.MemberGroup == SerializationMemberGroup.Collection)
                    {
                        var sourceCollection = memberValue.Value as IEnumerable;

                        if (member.MemberType.IsArrayEx())
                        {
                            var elementType = member.MemberType.GetElementTypeEx();
                            member.Value = sourceCollection.ToArray(elementType);
                        }
                        else
                        {
                            var targetCollection = TypeFactory.CreateInstance(member.MemberType) as IList;
                            if (targetCollection == null)
                            {
                                throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a collection, but target model cannot be updated because it does not implement IList",
                                                                                          context.ModelTypeName);
                            }

                            if (sourceCollection != null)
                            {
                                foreach (var item in sourceCollection)
                                {
                                    targetCollection.Add(item);
                                }
                            }

                            member.Value = targetCollection;
                        }
                    }
                    else
                    {
                        member.Value = memberValue.Value;
                    }

                    deserializedMemberValues.Add(memberValue);

                    foreach (var serializerModifier in serializerModifiers)
                    {
                        serializerModifier.DeserializeMember(context, member);
                        memberValue.Value = member.Value;
                    }

                    AfterDeserializeMember(context, member);
                    memberValue.Value = member.Value;

                    DeserializedMember.SafeInvoke(this, memberSerializationEventArgs);
                    memberValue.Value = member.Value;
                }
            }

            if (deserializedMemberValues.Count > 0)
            {
                var firstMember = deserializedMemberValues[0];
                if (firstMember.MemberGroup == SerializationMemberGroup.SimpleRootObject)
                {
                    // Completely replace root object (this is a basic (non-reference) type)
                    context.Model = firstMember.Value;
                }
                else if (firstMember.MemberGroup == SerializationMemberGroup.Dictionary)
                {
                    var targetDictionary = context.Model as IDictionary;
                    if (targetDictionary == null)
                    {
                        throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a dictionary, but target model cannot be updated because it does not implement IDictionary",
                                                                                  context.ModelTypeName);
                    }

                    targetDictionary.Clear();

                    var sourceDictionary = firstMember.Value as IDictionary;
                    if (sourceDictionary != null)
                    {
                        foreach (var key in sourceDictionary.Keys)
                        {
                            targetDictionary.Add(key, sourceDictionary[key]);
                        }
                    }
                }
                else if (firstMember.MemberGroup == SerializationMemberGroup.Collection)
                {
                    if (context.ModelType.IsArrayEx())
                    {
                        context.Model = firstMember.Value;
                    }
                    else
                    {
                        var targetCollection = context.Model as IList;
                        if (targetCollection == null)
                        {
                            throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a collection, but target model cannot be updated because it does not implement IList",
                                                                                      context.ModelTypeName);
                        }

                        targetCollection.Clear();

                        var sourceCollection = firstMember.Value as IEnumerable;
                        if (sourceCollection != null)
                        {
                            foreach (var item in sourceCollection)
                            {
                                targetCollection.Add(item);
                            }
                        }
                    }
                }
                else
                {
                    PopulateModel(context.Model, deserializedMemberValues.ToArray());
                }
            }

            return(deserializedMemberValues);
        }
        /// <summary>
        /// Ends member deserialization by invoking all the right events and running the modifiers.
        /// </summary>
        /// <param name="context">The serialization context.</param>
        /// <param name="member">The member that has been deserialized.</param>
        /// <param name="serializationObject">Result of the member deserialization.</param>
        /// <param name="serializerModifiers">The serializer modifiers.</param>
        protected virtual MemberValue EndMemberDeserialization(ISerializationContext <TSerializationContextInfo> context, MemberValue member,
                                                               SerializationObject serializationObject, IEnumerable <ISerializerModifier> serializerModifiers)
        {
            if (!serializationObject.IsSuccessful)
            {
                return(null);
            }

            // Note that we need to sync the member values every time
            var memberValue = new MemberValue(member.MemberGroup, member.ModelType, member.MemberType, member.Name,
                                              member.NameForSerialization, serializationObject.MemberValue);

            if (memberValue.MemberGroup == SerializationMemberGroup.Dictionary ||
                ShouldSerializeAsDictionary(member))
            {
                var targetDictionary = TypeFactory.CreateInstance(member.MemberType) as IDictionary;
                if (targetDictionary is null)
                {
                    throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a dictionary, but target model cannot be updated because it does not implement IDictionary",
                                                                              context.ModelTypeName);
                }

                var enumerable = memberValue.Value as List <SerializableKeyValuePair>;
                if (enumerable != null)
                {
                    foreach (var item in enumerable)
                    {
                        targetDictionary.Add(item.Key, item.Value);
                    }
                }
                else
                {
                    var sourceDictionary = memberValue.Value as IDictionary;
                    if (sourceDictionary != null)
                    {
                        foreach (var key in sourceDictionary.Keys)
                        {
                            targetDictionary.Add(key, sourceDictionary[key]);
                        }
                    }
                }

                member.Value = targetDictionary;
            }
            else if (memberValue.MemberGroup == SerializationMemberGroup.Collection)
            {
                var sourceCollection = memberValue.Value as IEnumerable;

                if (member.MemberType.IsArrayEx())
                {
                    var elementType = member.MemberType.GetElementTypeEx();
                    member.Value = sourceCollection.ToArray(elementType);
                }
                else
                {
                    var targetCollection = TypeFactory.CreateInstance(member.MemberType) as IList;
                    if (targetCollection is null)
                    {
                        throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a collection, but target model cannot be updated because it does not implement IList",
                                                                                  context.ModelTypeName);
                    }

                    if (sourceCollection != null)
                    {
                        foreach (var item in sourceCollection)
                        {
                            targetCollection.Add(item);
                        }
                    }

                    member.Value = targetCollection;
                }
            }
            else
            {
                member.Value = memberValue.Value;
            }

            foreach (var serializerModifier in serializerModifiers)
            {
                serializerModifier.DeserializeMember(context, member);
                memberValue.Value = member.Value;
            }

            AfterDeserializeMember(context, member);
            memberValue.Value = member.Value;

            DeserializedMember?.Invoke(this, new MemberSerializationEventArgs(context, member));
            memberValue.Value = member.Value;

            return(memberValue);
        }