| File: System\Runtime\Serialization\ReflectionXmlFormatReader.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.DataContractSerialization\src\System.Private.DataContractSerialization.csproj (System.Private.DataContractSerialization) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Reflection.Emit; using System.Runtime.Serialization.DataContracts; using System.Security; using System.Xml; using System.Xml.Schema; namespace System.Runtime.Serialization { internal sealed class ReflectionXmlClassReader { private readonly ClassDataContract _classContract; private readonly ReflectionReader _reflectionReader; public ReflectionXmlClassReader(ClassDataContract classDataContract) { Debug.Assert(classDataContract != null); _classContract = classDataContract; _reflectionReader = new ReflectionXmlReader(); } [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public object ReflectionReadClass(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context, XmlDictionaryString[]? memberNames, XmlDictionaryString[]? memberNamespaces) { return _reflectionReader.ReflectionReadClass(xmlReader, context, memberNames, memberNamespaces, _classContract); } } internal sealed class ReflectionXmlCollectionReader { private readonly ReflectionReader _reflectionReader = new ReflectionXmlReader(); [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public object ReflectionReadCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract) { return _reflectionReader.ReflectionReadCollection(xmlReader, context, itemName, itemNamespace/*itemNamespace*/, collectionContract); } [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public void ReflectionReadGetOnlyCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNs, CollectionDataContract collectionContract) { _reflectionReader.ReflectionReadGetOnlyCollection(xmlReader, context, itemName, itemNs, collectionContract); } } internal sealed class ReflectionXmlReader : ReflectionReader { [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] protected override void ReflectionReadMembers(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[]? memberNamespaces, ClassDataContract classContract, ref object obj) { Debug.Assert(memberNamespaces != null); int memberCount = classContract.MemberNames!.Length; context.IncrementItemCount(memberCount); int memberIndex = -1; int firstRequiredMember; _ = GetRequiredMembers(classContract, out firstRequiredMember); bool hasRequiredMembers = (firstRequiredMember < memberCount); int requiredIndex = hasRequiredMembers ? firstRequiredMember : -1; DataMember[] members = new DataMember[memberCount]; int reflectedMemberCount = ReflectionGetMembers(classContract, members); Debug.Assert(reflectedMemberCount == memberCount, "The value returned by ReflectionGetMembers() should equal to memberCount."); ExtensionDataObject? extensionData = null; if (classContract.HasExtensionData) { extensionData = new ExtensionDataObject(); ((IExtensibleDataObject)obj).ExtensionData = extensionData; } while (true) { if (!XmlObjectSerializerReadContext.MoveToNextElement(xmlReader)) { return; } if (hasRequiredMembers) { memberIndex = context.GetMemberIndexWithRequiredMembers(xmlReader, memberNames, memberNamespaces, memberIndex, requiredIndex, extensionData); } else { memberIndex = context.GetMemberIndex(xmlReader, memberNames, memberNamespaces, memberIndex, extensionData); } // GetMemberIndex returns memberNames.Length if member not found if (memberIndex < members.Length) { ReflectionReadMember(xmlReader, context, classContract, ref obj, memberIndex, members); requiredIndex = memberIndex + 1; } } } protected override string GetClassContractNamespace(ClassDataContract classContract) { return classContract.XmlName!.Namespace; } protected override string GetCollectionContractItemName(CollectionDataContract collectionContract) { return collectionContract.ItemName; } protected override string GetCollectionContractNamespace(CollectionDataContract collectionContract) { return collectionContract.XmlName.Namespace; } [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] protected override object? ReflectionReadDictionaryItem(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract) { Debug.Assert(collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary); context.ReadAttributes(xmlReader); return collectionContract.ItemContract.ReadXmlValue(xmlReader, context); } private static bool[] GetRequiredMembers(ClassDataContract contract, out int firstRequiredMember) { int memberCount = contract.MemberNames!.Length; bool[] requiredMembers = new bool[memberCount]; GetRequiredMembers(contract, requiredMembers); for (firstRequiredMember = 0; firstRequiredMember < memberCount; firstRequiredMember++) if (requiredMembers[firstRequiredMember]) break; return requiredMembers; } private static int GetRequiredMembers(ClassDataContract contract, bool[] requiredMembers) { int memberCount = (contract.BaseClassContract == null) ? 0 : GetRequiredMembers(contract.BaseClassContract, requiredMembers); List<DataMember> members = contract.Members!; for (int i = 0; i < members.Count; i++, memberCount++) { requiredMembers[memberCount] = members[i].IsRequired; } return memberCount; } } }