internal void WriteXml(XmlWriter writer, object value, XmlMember member, XmlTypeContext typeContext)
        {
            XmlMember   lastMember   = currentMember;
            XmlContract lastContract = currentContract;

            currentMember   = member;
            currentContract = typeContext.Contract;

            typeContext.WriteXml(writer, value, this);

            currentMember   = lastMember;
            currentContract = lastContract;
        }
        internal object ReadXml(XmlReader reader, XmlMember member, XmlTypeContext typeContext)
        {
            XmlMember   lastMember   = currentMember;
            XmlContract lastContract = currentContract;

            currentMember   = member;
            currentContract = typeContext.Contract;

            object value = typeContext.ReadXml(reader, this);

            currentMember   = lastMember;
            currentContract = lastContract;

            return(value);
        }
        private void SerializeBody(XmlWriter writer, object value, Type memberType, XmlMember member)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            if (value == null)
            {
                WriteNull(writer, memberType, member);
            }
            else
            {
                XmlTypeContext typeContext = settings.GetTypeContext(memberType);
                WriteXml(writer, value, member ?? typeContext.Contract.Root, typeContext);
            }
        }
        private object Deserialize(XmlReader reader, Type valueType, XmlMember member)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            if (valueType == null)
            {
                throw new ArgumentNullException("valueType");
            }

            if (initialState && reader.NodeType == XmlNodeType.None)
            {
                initialState = false;

                while (reader.NodeType != XmlNodeType.Element)
                {
                    if (!reader.Read())
                    {
                        return(null);
                    }
                }
            }

            if (reader.NodeType == XmlNodeType.Element)
            {
                if (!ReadValueType(reader, ref valueType))
                {
                    reader.Skip();
                    return(null);
                }
            }

            XmlTypeContext typeInfo = settings.GetTypeContext(valueType);

            if (member == null)
            {
                member = typeInfo.Contract.Root;
            }

            return(ReadXml(reader, member, typeInfo));
        }
Esempio n. 5
0
        private XmlTypeContext CreateTypeContext(Type valueType, XmlTypeContext context)
        {
            IXmlConverter readConverter  = null;
            IXmlConverter writeConverter = null;

            foreach (var converter in converters.Concat(DefaultConverters))
            {
                if (readConverter == null && converter.CanRead(valueType))
                {
                    readConverter = converter;

                    if (writeConverter != null)
                    {
                        break;
                    }
                }

                if (writeConverter == null && converter.CanWrite(valueType))
                {
                    writeConverter = converter;

                    if (readConverter != null)
                    {
                        break;
                    }
                }
            }

            var contract = contractResolver.ResolveContract(valueType);

            readConverter  = GetConverter(contract, readConverter);
            writeConverter = GetConverter(contract, writeConverter);

            context = new XmlTypeContext(contract, readConverter, writeConverter);
            typeContextCache.TryAdd(valueType, context);
            return(context);
        }
        internal void WriteElement(XmlWriter writer, object value, XmlMember member, XmlTypeContext context, Type valueType, bool shouldWriteTypeName)
        {
            var contractValueType = context.Contract.ValueType;

            if (!Settings.IsBuildingObjectGraph)
            {
                writer.WriteStartElement(member.Name);

                if (initialState)
                {
                    initialState = false;
                    WriteNamespaces(writer);
                }

                if (shouldWriteTypeName)
                {
                    WriteTypeName(writer, valueType);
                }
            }

            object referencedValue = value;

            if (value is IAnyOptional optValue && optValue.HasValue)
            {
                contractValueType = optValue.GetInnerType();
                referencedValue   = optValue.Value;
            }

            var isCollection = !contractValueType.Equals(typeof(string)) &&
                               contractValueType.IsEnumerable();

            var isModel = contractValueType.IsClass && contractValueType != typeof(string);

            if (context.Contract is XmlObjectContract && isModel && !isCollection)
            {
                long id = settings.ReferenceHandlingGenerator.GetId(referencedValue, out bool firstTime);

                if (Settings.IsBuildingObjectGraph)
                {
                    if (firstTime)
                    {
                        _xmlReferenceLevelLookup.Add(id, currentLevel);
                        currentLevel++;
                        WriteXml(writer, value, member, context);
                        currentLevel--;
                    }
                    else
                    {
                        if (Settings.ReferenceHandling == XmlReferenceHandling.Throw)
                        {
                            throw new Exception("Found reference loop. Please set ReferenceHandling setting to XmlReferenceHandling.Handle");
                        }
                        if (currentLevel < _xmlReferenceLevelLookup[id])
                        {
                            _xmlReferenceLevelLookup[id] = currentLevel;
                        }
                    }
                    // stop processing
                    return;
                }

                bool isExpansionElement = Settings.ReferenceExpansion == XmlReferenceExpansion.FirstAccessed
                    ? firstTime
                    : currentLevel == _xmlReferenceLevelLookup[id];
                if (isExpansionElement)
                {
                    if (Settings.ReferenceExpansion == XmlReferenceExpansion.HighestLevel)
                    {
                        // element should only be expanded once - prevents expansion of elements on the same level
                        _xmlReferenceLevelLookup[id] = -1;
                    }
                    if (Settings.ReferenceHandling == XmlReferenceHandling.Handle)
                    {
                        writer.WriteAttributeString(Settings.ReferenceHandlingIdName, id.ToString());
                    }
                    currentLevel++;
                    WriteXml(writer, value, member, context);
                    currentLevel--;
                }
                else
                {
                    if (Settings.ReferenceHandling == XmlReferenceHandling.Throw)
                    {
                        throw new Exception("Found reference loop. Please set ReferenceHandling setting to XmlReferenceHandling.Handle");
                    }
                    writer.WriteAttributeString(Settings.ReferenceHandlingReferenceName, id.ToString());
                }
            }
            else
            {
                if (!Settings.IsBuildingObjectGraph || isCollection)
                {
                    WriteXml(writer, value, member, context);
                }
            }

            if (!Settings.IsBuildingObjectGraph)
            {
                writer.WriteEndElement();
            }
        }
        private void Serialize(XmlWriter writer, object value, Type memberType, XmlMember member)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            // ignore optional values with none value
            if (value is IAnyOptional optional)
            {
                if (!optional.HasValue)
                {
                    if (Settings.NoneValueHandling == XmlNoneValueHandling.Ignore)
                    {
                        return;
                    }
                    // Output default values for inner types
                    var innerType         = optional.GetInnerType();
                    var nullableInnerType = innerType.GetUnderlyingNullableType();
                    if (nullableInnerType != null)
                    {
                        WriteNull(writer, memberType, member);
                        return;
                    }
                    else if (innerType.IsClass)
                    {
                        WriteNull(writer, memberType, member);
                        return;
                    }
                }
                else if (optional.Value == null)
                {
                    WriteNull(writer, memberType, member);
                    return;
                }
            }

            if (value == null)
            {
                WriteNull(writer, memberType, member);
                return;
            }

            if (settings.EmptyCollectionHandling == XmlEmptyCollectionHandling.Ignore && value.IsEmpty() == true)
            {
                return;
            }


            XmlTypeContext context = null;

            if (member == null)
            {
                context = settings.GetTypeContext(memberType);
                member  = context.Contract.Root;
            }

            bool shouldWriteTypeName = TryResolveValueType(value, ref member, out Type valueType);

            if (member.DefaultValue != null)
            {
                XmlDefaultValueHandling defaultValueHandling = member.DefaultValueHandling ?? settings.DefaultValueHandling;

                if (defaultValueHandling == XmlDefaultValueHandling.Ignore && value.Equals(member.DefaultValue))
                {
                    return;
                }
            }

            if (context == null || context.Contract.ValueType != member.ValueType)
            {
                context = settings.GetTypeContext(valueType);
            }

            switch (member.MappingType)
            {
            case XmlMappingType.Element:
                WriteElement(writer, value, member, context, valueType, shouldWriteTypeName);
                break;

            case XmlMappingType.Attribute:
                if (!Settings.IsBuildingObjectGraph)
                {
                    writer.WriteStartAttribute(member.Name);
                }

                WriteXml(writer, value, member, context);

                if (!Settings.IsBuildingObjectGraph)
                {
                    writer.WriteEndAttribute();
                }
                break;

            case XmlMappingType.InnerText:
                if (!Settings.IsBuildingObjectGraph)
                {
                    WriteXml(writer, value, member, context);
                }
                break;
            }
        }