File: System\Runtime\Serialization\DataContractSet.cs
Web Access
Project: src\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.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Xml;
using System.Xml.Schema;
 
using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, System.Runtime.Serialization.DataContracts.DataContract>;
 
namespace System.Runtime.Serialization.DataContracts
{
    public sealed class DataContractSet
    {
        private DataContractDictionary? _contracts;
        private Dictionary<DataContract, object>? _processedContracts;
        private readonly ISerializationSurrogateProvider? _surrogateProvider;
        private readonly ISerializationSurrogateProvider2? _extendedSurrogateProvider;
        private Hashtable? _surrogateData;
        private DataContractDictionary? _knownTypesForObject;
        private readonly List<Type>? _referencedTypes;
        private readonly List<Type>? _referencedCollectionTypes;
 
        public DataContractSet(ISerializationSurrogateProvider? dataContractSurrogate, IEnumerable<Type>? referencedTypes, IEnumerable<Type>? referencedCollectionTypes)
        {
            _surrogateProvider = dataContractSurrogate;
            _extendedSurrogateProvider = dataContractSurrogate as ISerializationSurrogateProvider2;
            _referencedTypes = referencedTypes != null ? new List<Type>(referencedTypes) : null;
            _referencedCollectionTypes = referencedCollectionTypes != null ? new List<Type>(referencedCollectionTypes) : null;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        public DataContractSet(DataContractSet dataContractSet)
        {
            ArgumentNullException.ThrowIfNull(dataContractSet);
 
            _referencedTypes = dataContractSet._referencedTypes;
            _referencedCollectionTypes = dataContractSet._referencedCollectionTypes;
            _extendedSurrogateProvider = dataContractSet._extendedSurrogateProvider;
 
            foreach (KeyValuePair<XmlQualifiedName, DataContract> pair in dataContractSet.Contracts)
            {
                InternalAdd(pair.Key, pair.Value);
            }
 
            if (dataContractSet._processedContracts != null)
            {
                foreach (KeyValuePair<DataContract, object> pair in dataContractSet._processedContracts)
                {
                    ProcessedContracts.Add(pair.Key, pair.Value);
                }
            }
        }
 
        public DataContractDictionary Contracts =>
            _contracts ??= new DataContractDictionary();
 
        public Dictionary<DataContract, object> ProcessedContracts =>
            _processedContracts ??= new Dictionary<DataContract, object>();
 
        public Hashtable SurrogateData => _surrogateData ??= new Hashtable();
 
        public DataContractDictionary? KnownTypesForObject
        {
            get => _knownTypesForObject;
            internal set => _knownTypesForObject = value;
        }
 
        internal static void EnsureTypeNotGeneric(Type type)
        {
            if (type.ContainsGenericParameters)
                throw new InvalidDataContractException(SR.Format(SR.GenericTypeNotExportable, type));
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal void Add(Type type)
        {
            DataContract dataContract = GetDataContract(type);
            EnsureTypeNotGeneric(dataContract.UnderlyingType);
            Add(dataContract);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private void Add(DataContract dataContract)
        {
            Add(dataContract.XmlName, dataContract);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal void Add(XmlQualifiedName name, DataContract dataContract)
        {
            if (dataContract.IsBuiltInDataContract)
                return;
            InternalAdd(name, dataContract);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal void InternalAdd(XmlQualifiedName name, DataContract dataContract)
        {
            if (Contracts.TryGetValue(name, out DataContract? dataContractInSet))
            {
                if (!dataContractInSet.Equals(dataContract))
                {
                    if (dataContract.UnderlyingType == null || dataContractInSet.UnderlyingType == null)
                        throw new InvalidOperationException(SR.Format(SR.DupContractInDataContractSet, dataContract.XmlName.Name, dataContract.XmlName.Namespace));
                    else
                    {
                        bool typeNamesEqual = (DataContract.GetClrTypeFullName(dataContract.UnderlyingType) == DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType));
                        throw new InvalidOperationException(SR.Format(SR.DupTypeContractInDataContractSet, (typeNamesEqual ? dataContract.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContract.UnderlyingType)), (typeNamesEqual ? dataContractInSet.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType)), dataContract.XmlName.Name, dataContract.XmlName.Namespace));
                    }
                }
            }
            else
            {
                Contracts.Add(name, dataContract);
 
                if (dataContract is ClassDataContract classDC)
                {
                    AddClassDataContract(classDC);
                }
                else if (dataContract is CollectionDataContract collectionDC)
                {
                    AddCollectionDataContract(collectionDC);
                }
                else if (dataContract is XmlDataContract xmlDC)
                {
                    AddXmlDataContract(xmlDC);
                }
            }
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private void AddClassDataContract(ClassDataContract classDataContract)
        {
            if (classDataContract.BaseClassContract != null)
            {
                Add(classDataContract.BaseClassContract.XmlName, classDataContract.BaseClassContract);
            }
            if (!classDataContract.IsISerializable)
            {
                if (classDataContract.Members != null)
                {
                    for (int i = 0; i < classDataContract.Members.Count; i++)
                    {
                        DataMember dataMember = classDataContract.Members[i];
                        DataContract memberDataContract = GetMemberTypeDataContract(dataMember);
 
                        if (_extendedSurrogateProvider != null && dataMember.MemberInfo != null)
                        {
                            object? customData = DataContractSurrogateCaller.GetCustomDataToExport(
                                                    _extendedSurrogateProvider,
                                                    dataMember.MemberInfo,
                                                    memberDataContract.UnderlyingType);
                            if (customData != null)
                                SurrogateData.Add(dataMember, customData);
                        }
 
                        Add(memberDataContract.XmlName, memberDataContract);
                    }
                }
            }
            AddKnownDataContracts(classDataContract.KnownDataContracts);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private void AddCollectionDataContract(CollectionDataContract collectionDataContract)
        {
            if (collectionDataContract.UnderlyingType != Globals.TypeOfSchemaDefinedType)
            {
                if (collectionDataContract.IsDictionary)
                {
                    ClassDataContract keyValueContract = (collectionDataContract.ItemContract as ClassDataContract)!;
                    AddClassDataContract(keyValueContract);
                }
                else
                {
                    DataContract itemContract = GetItemTypeDataContract(collectionDataContract);
                    if (itemContract != null)
                        Add(itemContract.XmlName, itemContract);
                }
            }
            AddKnownDataContracts(collectionDataContract.KnownDataContracts);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private void AddXmlDataContract(XmlDataContract xmlDataContract)
        {
            AddKnownDataContracts(xmlDataContract.KnownDataContracts);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private void AddKnownDataContracts(DataContractDictionary? knownDataContracts)
        {
            if (knownDataContracts?.Count > 0)
            {
                foreach (DataContract knownDataContract in knownDataContracts.Values)
                {
                    Add(knownDataContract);
                }
            }
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal XmlQualifiedName GetXmlName(Type clrType)
        {
            if (_surrogateProvider != null)
            {
                Type dcType = DataContractSurrogateCaller.GetDataContractType(_surrogateProvider, clrType);
                return DataContract.GetXmlName(dcType);
            }
            return DataContract.GetXmlName(clrType);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        public DataContract GetDataContract(Type type)
        {
            if (_surrogateProvider == null)
                return DataContract.GetDataContract(type);
 
            DataContract? dataContract = DataContract.GetBuiltInDataContract(type);
            if (dataContract != null)
                return dataContract;
 
            Type dcType = DataContractSurrogateCaller.GetDataContractType(_surrogateProvider, type);
            dataContract = DataContract.GetDataContract(dcType);
            if (_extendedSurrogateProvider != null && !SurrogateData.Contains(dataContract))
            {
                object? customData = DataContractSurrogateCaller.GetCustomDataToExport(_extendedSurrogateProvider, type, dcType);
                if (customData != null)
                    SurrogateData.Add(dataContract, customData);
            }
 
            return dataContract;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        public DataContract? GetDataContract(XmlQualifiedName key)
        {
            DataContract? dataContract = DataContract.GetBuiltInDataContract(key.Name, key.Namespace);
            if (dataContract == null)
            {
                Contracts.TryGetValue(key, out dataContract);
            }
            return dataContract;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal DataContract GetMemberTypeDataContract(DataMember dataMember)
        {
            if (dataMember.MemberInfo is not Type)
            {
                Type dataMemberType = dataMember.MemberType;
                if (dataMember.IsGetOnlyCollection)
                {
                    if (_surrogateProvider != null)
                    {
                        Type dcType = DataContractSurrogateCaller.GetDataContractType(_surrogateProvider, dataMemberType);
                        if (dcType != dataMemberType)
                        {
                            throw new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupported,
                                DataContract.GetClrTypeFullName(dataMemberType),
                                (dataMember.MemberInfo.DeclaringType != null) ? DataContract.GetClrTypeFullName(dataMember.MemberInfo.DeclaringType) : dataMember.MemberInfo.DeclaringType,
                                dataMember.MemberInfo.Name));
                        }
                    }
                    return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(dataMemberType.TypeHandle), dataMemberType.TypeHandle, dataMemberType);
                }
                else
                {
                    return GetDataContract(dataMemberType);
                }
            }
            return dataMember.MemberTypeContract;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal DataContract GetItemTypeDataContract(CollectionDataContract collectionContract)
        {
            if (collectionContract.ItemType != null)
                return GetDataContract(collectionContract.ItemType);
            return collectionContract.ItemContract;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal bool Remove(XmlQualifiedName key)
        {
            if (DataContract.GetBuiltInDataContract(key.Name, key.Namespace) != null)
                return false;
            return Contracts.Remove(key);
        }
 
        private Dictionary<XmlQualifiedName, object>? _referencedTypesDictionary;
        private Dictionary<XmlQualifiedName, object>? _referencedCollectionTypesDictionary;
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private Dictionary<XmlQualifiedName, object> GetReferencedTypes()
        {
            if (_referencedTypesDictionary == null)
            {
                _referencedTypesDictionary = new Dictionary<XmlQualifiedName, object>();
                //Always include Nullable as referenced type
                //Do not allow surrogating Nullable<T>
                _referencedTypesDictionary.Add(DataContract.GetXmlName(Globals.TypeOfNullable), Globals.TypeOfNullable);
                if (_referencedTypes != null)
                {
                    foreach (Type type in _referencedTypes)
                    {
                        if (type == null)
                            throw new InvalidOperationException(SR.Format(SR.ReferencedTypesCannotContainNull));
 
                        AddReferencedType(_referencedTypesDictionary, type);
                    }
                }
            }
            return _referencedTypesDictionary;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private Dictionary<XmlQualifiedName, object> GetReferencedCollectionTypes()
        {
            if (_referencedCollectionTypesDictionary == null)
            {
                _referencedCollectionTypesDictionary = new Dictionary<XmlQualifiedName, object>();
                if (_referencedCollectionTypes != null)
                {
                    foreach (Type type in _referencedCollectionTypes)
                    {
                        if (type == null)
                            throw new InvalidOperationException(SR.Format(SR.ReferencedCollectionTypesCannotContainNull));
                        AddReferencedType(_referencedCollectionTypesDictionary, type);
                    }
                }
                XmlQualifiedName genericDictionaryName = DataContract.GetXmlName(Globals.TypeOfDictionaryGeneric);
                if (!_referencedCollectionTypesDictionary.ContainsKey(genericDictionaryName) && GetReferencedTypes().ContainsKey(genericDictionaryName))
                    AddReferencedType(_referencedCollectionTypesDictionary, Globals.TypeOfDictionaryGeneric);
            }
            return _referencedCollectionTypesDictionary;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private void AddReferencedType(Dictionary<XmlQualifiedName, object> referencedTypes, Type type)
        {
            if (IsTypeReferenceable(type))
            {
                XmlQualifiedName xmlName;
                try
                {
                    xmlName = GetXmlName(type);
                }
                catch (InvalidDataContractException)
                {
                    // Type not referenceable if we can't get a xml name.
                    return;
                }
                catch (InvalidOperationException)
                {
                    // Type not referenceable if we can't get a xml name.
                    return;
                }
 
                if (referencedTypes.TryGetValue(xmlName, out object? value))
                {
                    if (value is Type referencedType)
                    {
                        if (referencedType != type)
                        {
                            referencedTypes.Remove(xmlName);
                            List<Type> types = new List<Type>();
                            types.Add(referencedType);
                            types.Add(type);
                            referencedTypes.Add(xmlName, types);
                        }
                    }
                    else
                    {
                        List<Type> types = (List<Type>)value;
                        if (!types.Contains(type))
                            types.Add(type);
                    }
                }
                else
                    referencedTypes.Add(xmlName, type);
            }
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private static bool IsTypeReferenceable(Type type)
        {
            try
            {
                return (
#pragma warning disable SYSLIB0050 // Type.IsSerializable is obsolete
                        type.IsSerializable ||
#pragma warning restore SYSLIB0050
                        type.IsDefined(Globals.TypeOfDataContractAttribute, false) ||
                        (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type) && !type.IsGenericTypeDefinition) ||
                        CollectionDataContract.IsCollection(type, out _) ||
                        ClassDataContract.IsNonAttributedTypeValidForSerialization(type));
            }
            catch (Exception ex) when (!ExceptionUtility.IsFatal(ex))
            {
                // An exception can be thrown in the designer when a project has a runtime binding redirection for a referenced assembly or a reference dependent assembly.
                // Type.IsDefined is known to throw System.IO.FileLoadException.
                // ClassDataContract.IsNonAttributedTypeValidForSerialization is known to throw System.IO.FileNotFoundException.
                // We guard against all non-critical exceptions.
            }
 
            return false;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        public Type? GetReferencedType(XmlQualifiedName xmlName, DataContract dataContract, out DataContract? referencedContract, out object[]? genericParameters, bool? supportGenericTypes = null)
        {
            Type? type = GetReferencedTypeInternal(xmlName, dataContract);
            referencedContract = null;
            genericParameters = null;
 
            if (supportGenericTypes == null)
                return type;
 
            if (type != null && !type.IsGenericTypeDefinition && !type.ContainsGenericParameters)
                return type;
 
            if (dataContract.GenericInfo == null)
                return null;
 
            XmlQualifiedName genericXmlName = dataContract.GenericInfo.GetExpandedXmlName();
            if (genericXmlName != dataContract.XmlName)
                throw new InvalidDataContractException(SR.Format(SR.GenericTypeNameMismatch, dataContract.XmlName.Name, dataContract.XmlName.Namespace, genericXmlName.Name, genericXmlName.Namespace));
 
            // This check originally came "here" in the old code. Its tempting to move it up with the GenericInfo check.
            if (!supportGenericTypes.Value)
                return null;
 
            type = GetReferencedGenericTypeInternal(dataContract.GenericInfo, out referencedContract, out genericParameters);
            return type;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private Type? GetReferencedGenericTypeInternal(GenericInfo genInfo, out DataContract? referencedContract, out object[]? genericParameters)
        {
            genericParameters = null;
            referencedContract = null;
 
            Type? type = GetReferencedTypeInternal(genInfo.XmlName, null);
 
            if (type == null)
            {
                if (genInfo.Parameters != null)
                    return null;
 
                referencedContract = GetDataContract(genInfo.XmlName);
                if (referencedContract != null && referencedContract.GenericInfo != null)
                    referencedContract = null;
 
                return null;    // No type, but maybe we found a suitable referenced contract?
            }
 
            // We've got a type. But its generic. So we need some parameter contracts.
            // referencedContract is still null, but will be set if we can verify all parameters.
            if (genInfo.Parameters != null)
            {
                bool enableStructureCheck = (type != Globals.TypeOfNullable);
                genericParameters = new object[genInfo.Parameters.Count];
                DataContract[] structureCheckContracts = new DataContract[genInfo.Parameters.Count];
                for (int i = 0; i < genInfo.Parameters.Count; i++)
                {
                    GenericInfo paramInfo = genInfo.Parameters[i];
                    XmlQualifiedName paramXmlName = paramInfo.GetExpandedXmlName();
                    DataContract? paramContract = GetDataContract(paramXmlName);
 
                    if (paramContract != null)
                    {
                        genericParameters[i] = paramContract;
                    }
                    else
                    {
                        Type? paramType = GetReferencedGenericTypeInternal(paramInfo, out paramContract, out object[]? paramParameters);
                        if (paramType != null)
                        {
                            genericParameters[i] = new Tuple<Type, object[]?>(paramType, paramParameters);
                        }
                        else
                        {
                            genericParameters[i] = paramContract!;
                        }
                    }
 
                    structureCheckContracts[i] = paramContract!;    // This is ok. If it's null, we disable the use of this array in the next line.
                    if (paramContract == null)
                        enableStructureCheck = false;
                }
                if (enableStructureCheck)
                    referencedContract = DataContract.GetDataContract(type).BindGenericParameters(structureCheckContracts);
            }
 
            return type;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private Type? GetReferencedTypeInternal(XmlQualifiedName xmlName, DataContract? dataContract)
        {
            Type? type;
 
            if (dataContract == null)
            {
                if (TryGetReferencedCollectionType(xmlName, null, out type))
                    return type;
                if (TryGetReferencedType(xmlName, null, out type))
                {
                    // enforce that collection types only be specified via ReferencedCollectionTypes
                    if (CollectionDataContract.IsCollection(type))
                        return null;
 
                    return type;
                }
            }
            else if (dataContract is CollectionDataContract)
            {
                if (TryGetReferencedCollectionType(xmlName, dataContract, out type))
                    return type;
            }
            else
            {
                if (dataContract is XmlDataContract xmlDataContract && xmlDataContract.IsAnonymous)
                    xmlName = SchemaImporter.ImportActualType(xmlDataContract.XsdType?.Annotation, xmlName, dataContract.XmlName);
 
                if (TryGetReferencedType(xmlName, dataContract, out type))
                    return type;
            }
            return null;
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal bool TryGetReferencedType(XmlQualifiedName xmlName, DataContract? dataContract, [NotNullWhen(true)] out Type? type)
        {
            return TryGetReferencedType(xmlName, dataContract, false/*useReferencedCollectionTypes*/, out type);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        internal bool TryGetReferencedCollectionType(XmlQualifiedName xmlName, DataContract? dataContract, [NotNullWhen(true)] out Type? type)
        {
            return TryGetReferencedType(xmlName, dataContract, true/*useReferencedCollectionTypes*/, out type);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        private bool TryGetReferencedType(XmlQualifiedName xmlName, DataContract? dataContract, bool useReferencedCollectionTypes, [NotNullWhen(true)] out Type? type)
        {
            Dictionary<XmlQualifiedName, object> referencedTypes = useReferencedCollectionTypes ? GetReferencedCollectionTypes() : GetReferencedTypes();
            if (referencedTypes.TryGetValue(xmlName, out object? value))
            {
                type = value as Type;
                if (type != null)
                {
                    return true;
                }
                else
                {
                    // Throw ambiguous type match exception
                    List<Type> types = (List<Type>)value;
                    StringBuilder errorMessage = new StringBuilder();
                    bool containsGenericType = false;
                    for (int i = 0; i < types.Count; i++)
                    {
                        Type conflictingType = types[i];
                        if (!containsGenericType)
                            containsGenericType = conflictingType.IsGenericTypeDefinition;
                        errorMessage.AppendFormat("{0}\"{1}\" ", Environment.NewLine, conflictingType.AssemblyQualifiedName);
                        if (dataContract != null)
                        {
                            DataContract other = GetDataContract(conflictingType);
                            errorMessage.Append(SR.Format(((other != null && other.Equals(dataContract)) ? SR.ReferencedTypeMatchingMessage : SR.ReferencedTypeNotMatchingMessage)));
                        }
                    }
                    if (containsGenericType)
                    {
                        throw new InvalidOperationException(SR.Format(
                            (useReferencedCollectionTypes ? SR.AmbiguousReferencedCollectionTypes1 : SR.AmbiguousReferencedTypes1),
                            errorMessage.ToString()));
                    }
                    else
                    {
                        throw new InvalidOperationException(SR.Format(
                            (useReferencedCollectionTypes ? SR.AmbiguousReferencedCollectionTypes3 : SR.AmbiguousReferencedTypes3),
                            XmlConvert.DecodeName(xmlName.Name),
                            xmlName.Namespace,
                            errorMessage.ToString()));
                    }
                }
            }
            type = null;
            return false;
        }
 
        internal ISerializationSurrogateProvider2? SerializationExtendedSurrogateProvider => _extendedSurrogateProvider;
 
        internal object? GetSurrogateData(object key)
        {
            return SurrogateData[key];
        }
 
        internal void SetSurrogateData(object key, object? surrogateData)
        {
            SurrogateData[key] = surrogateData;
        }
 
        internal bool IsContractProcessed(DataContract dataContract)
        {
            return ProcessedContracts.ContainsKey(dataContract);
        }
 
        internal void SetContractProcessed(DataContract dataContract)
        {
            ProcessedContracts.Add(dataContract, dataContract);
        }
 
        internal IEnumerator<KeyValuePair<XmlQualifiedName, DataContract>> GetEnumerator()
        {
            return Contracts.GetEnumerator();
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        public void ImportSchemaSet(XmlSchemaSet schemaSet, IEnumerable<XmlQualifiedName>? typeNames, bool importXmlDataType)
        {
            SchemaImporter importer = new SchemaImporter(schemaSet, typeNames, null, this, importXmlDataType);
            importer.Import(out _);
        }
 
        [RequiresDynamicCode(DataContract.SerializerAOTWarning)]
        [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
        public List<XmlQualifiedName> ImportSchemaSet(XmlSchemaSet schemaSet, IEnumerable<XmlSchemaElement> elements, bool importXmlDataType)
        {
            SchemaImporter importer = new SchemaImporter(schemaSet, Array.Empty<XmlQualifiedName>() /* Needs to be empty, not null for 'elements' to be used. */, elements, this, importXmlDataType);
            importer.Import(out List<XmlQualifiedName>? elementNames);
            return elementNames!;   // Not null when we have provided non-null 'typeNames' and 'elements'
        }
    }
}