|
// 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;
}
}
}
|