File: FrameworkFork\System.Runtime.Serialization\System\Runtime\Serialization\XmlObjectSerializerContext.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace System.Runtime.Serialization
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;
    using System.Security;
    using Microsoft.Xml;
    using DataContractDictionary = System.Collections.Generic.Dictionary<Microsoft.Xml.XmlQualifiedName, DataContract>;
 
#if USE_REFEMIT || NET_NATIVE
    public class XmlObjectSerializerContext
#else
    internal class XmlObjectSerializerContext
#endif
    {
        protected XmlObjectSerializer serializer;
        protected DataContract rootTypeDataContract;
        internal ScopedKnownTypes scopedKnownTypes = new ScopedKnownTypes();
        protected DataContractDictionary serializerKnownDataContracts;
        private bool _isSerializerKnownDataContractsSetExplicit;
        protected IList<Type> serializerKnownTypeList;
        private int _itemCount;
        private int _maxItemsInObjectGraph;
        private StreamingContext _streamingContext;
        private bool _ignoreExtensionDataObject;
        private DataContractResolver _dataContractResolver;
        private KnownTypeDataContractResolver _knownTypeResolver;
 
        internal XmlObjectSerializerContext(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject,
                                            DataContractResolver dataContractResolver)
        {
            this.serializer = serializer;
            _itemCount = 1;
            _maxItemsInObjectGraph = maxItemsInObjectGraph;
            _streamingContext = streamingContext;
            _ignoreExtensionDataObject = ignoreExtensionDataObject;
            _dataContractResolver = dataContractResolver;
        }
 
        internal XmlObjectSerializerContext(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject)
            : this(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject, null)
        {
        }
 
        internal XmlObjectSerializerContext(DataContractSerializer serializer, DataContract rootTypeDataContract
                                                                                                                , DataContractResolver dataContractResolver
                                                                                                                                                           )
            : this(serializer,
            serializer.MaxItemsInObjectGraph,
            new StreamingContext(),
            serializer.IgnoreExtensionDataObject,
            dataContractResolver
            )
        {
            this.rootTypeDataContract = rootTypeDataContract;
            this.serializerKnownTypeList = serializer.knownTypeList;
        }
 
 
        internal virtual SerializationMode Mode
        {
            get { return SerializationMode.SharedContract; }
        }
 
        internal virtual bool IsGetOnlyCollection
        {
            get { return false; }
            set { }
        }
 
 
 
#if USE_REFEMIT
        public StreamingContext GetStreamingContext()
#else
        internal StreamingContext GetStreamingContext()
#endif
        {
            return _streamingContext;
        }
 
#if USE_REFEMIT
        public void IncrementItemCount(int count)
#else
        internal void IncrementItemCount(int count)
#endif
        {
            if (count > _maxItemsInObjectGraph - _itemCount)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(string.Format(SRSerialization.ExceededMaxItemsQuota, _maxItemsInObjectGraph)));
            _itemCount += count;
        }
 
        internal int RemainingItemCount
        {
            get { return _maxItemsInObjectGraph - _itemCount; }
        }
 
        internal bool IgnoreExtensionDataObject
        {
            get { return _ignoreExtensionDataObject; }
        }
 
        protected DataContractResolver DataContractResolver
        {
            get { return _dataContractResolver; }
        }
 
        protected KnownTypeDataContractResolver KnownTypeResolver
        {
            get
            {
                if (_knownTypeResolver == null)
                {
                    _knownTypeResolver = new KnownTypeDataContractResolver(this);
                }
                return _knownTypeResolver;
            }
        }
 
        internal DataContract GetDataContract(Type type)
        {
            return GetDataContract(type.TypeHandle, type);
        }
 
        internal virtual DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
        {
            if (IsGetOnlyCollection)
            {
                return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(typeHandle), typeHandle, type, Mode);
            }
            else
            {
                return DataContract.GetDataContract(typeHandle, type, Mode);
            }
        }
 
        internal virtual DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
        {
            if (IsGetOnlyCollection)
            {
                return DataContract.GetGetOnlyCollectionDataContractSkipValidation(typeId, typeHandle, type);
            }
            else
            {
                return DataContract.GetDataContractSkipValidation(typeId, typeHandle, type);
            }
        }
 
 
        internal virtual DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
        {
            if (IsGetOnlyCollection)
            {
                return DataContract.GetGetOnlyCollectionDataContract(id, typeHandle, null /*type*/, Mode);
            }
            else
            {
                return DataContract.GetDataContract(id, typeHandle, Mode);
            }
        }
 
        internal virtual void CheckIfTypeSerializable(Type memberType, bool isMemberTypeSerializable)
        {
            if (!isMemberTypeSerializable)
                throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(string.Format(SRSerialization.TypeNotSerializable, memberType)));
        }
 
        internal virtual Type GetSurrogatedType(Type type)
        {
            return type;
        }
        internal virtual DataContractDictionary SerializerKnownDataContracts
        {
            get
            {
                // This field must be initialized during construction by serializers using data contracts.
                if (!_isSerializerKnownDataContractsSetExplicit)
                {
                    this.serializerKnownDataContracts = serializer.KnownDataContracts;
                    _isSerializerKnownDataContractsSetExplicit = true;
                }
                return this.serializerKnownDataContracts;
            }
        }
 
        private DataContract GetDataContractFromSerializerKnownTypes(XmlQualifiedName qname)
        {
            DataContractDictionary serializerKnownDataContracts = this.SerializerKnownDataContracts;
            if (serializerKnownDataContracts == null)
                return null;
            DataContract outDataContract;
            return serializerKnownDataContracts.TryGetValue(qname, out outDataContract) ? outDataContract : null;
        }
 
        internal static DataContractDictionary GetDataContractsForKnownTypes(IList<Type> knownTypeList)
        {
            if (knownTypeList == null) return null;
            DataContractDictionary dataContracts = new DataContractDictionary();
            Dictionary<Type, Type> typesChecked = new Dictionary<Type, Type>();
            for (int i = 0; i < knownTypeList.Count; i++)
            {
                Type knownType = knownTypeList[i];
                if (knownType == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.NullKnownType, "knownTypes")));
 
                DataContract.CheckAndAdd(knownType, typesChecked, ref dataContracts);
            }
            return dataContracts;
        }
 
        internal bool IsKnownType(DataContract dataContract, DataContractDictionary knownDataContracts, Type declaredType)
        {
            bool knownTypesAddedInCurrentScope = false;
            if (knownDataContracts != null)
            {
                scopedKnownTypes.Push(knownDataContracts);
                knownTypesAddedInCurrentScope = true;
            }
 
            bool isKnownType = IsKnownType(dataContract, declaredType);
 
            if (knownTypesAddedInCurrentScope)
            {
                scopedKnownTypes.Pop();
            }
            return isKnownType;
        }
 
        internal bool IsKnownType(DataContract dataContract, Type declaredType)
        {
            DataContract knownContract = ResolveDataContractFromKnownTypes(dataContract.StableName.Name, dataContract.StableName.Namespace, null /*memberTypeContract*/ /*, declaredType */);
            return knownContract != null && knownContract.UnderlyingType == dataContract.UnderlyingType;
        }
 
        internal Type ResolveNameFromKnownTypes(XmlQualifiedName typeName)
        {
            DataContract dataContract = ResolveDataContractFromKnownTypes(typeName);
            return dataContract == null ? null : dataContract.UnderlyingType;
        }
 
        private DataContract ResolveDataContractFromKnownTypes(XmlQualifiedName typeName)
        {
            DataContract dataContract = PrimitiveDataContract.GetPrimitiveDataContract(typeName.Name, typeName.Namespace);
            if (dataContract == null)
            {
#if NET_NATIVE
                if (typeName.Name == Globals.SafeSerializationManagerName && typeName.Namespace == Globals.SafeSerializationManagerNamespace && Globals.TypeOfSafeSerializationManager != null)
                {
                    return GetDataContract(Globals.TypeOfSafeSerializationManager);
                }
#endif
                dataContract = scopedKnownTypes.GetDataContract(typeName);
                if (dataContract == null)
                {
                    dataContract = GetDataContractFromSerializerKnownTypes(typeName);
                }
            }
            return dataContract;
        }
 
        protected DataContract ResolveDataContractFromKnownTypes(string typeName, string typeNs, DataContract memberTypeContract)
        {
            XmlQualifiedName qname = new XmlQualifiedName(typeName, typeNs);
            DataContract dataContract;
            if (_dataContractResolver == null)
            {
                dataContract = ResolveDataContractFromKnownTypes(qname);
            }
            else
            {
                Type dataContractType = _dataContractResolver.ResolveName(typeName, typeNs, null, KnownTypeResolver);
                dataContract = dataContractType == null ? null : GetDataContract(dataContractType);
            }
            if (dataContract == null)
            {
                if (memberTypeContract != null
                    && !memberTypeContract.UnderlyingType.GetTypeInfo().IsInterface
                    && memberTypeContract.StableName == qname)
                {
                    dataContract = memberTypeContract;
                }
                if (dataContract == null && rootTypeDataContract != null)
                {
                    if (rootTypeDataContract.StableName == qname)
                        dataContract = rootTypeDataContract;
                    else
                    {
                        CollectionDataContract collectionContract = rootTypeDataContract as CollectionDataContract;
                        while (collectionContract != null)
                        {
                            DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType));
                            if (itemContract.StableName == qname)
                            {
                                dataContract = itemContract;
                                break;
                            }
                            collectionContract = itemContract as CollectionDataContract;
                        }
                    }
                }
            }
            return dataContract;
        }
 
        internal void PushKnownTypes(DataContract dc)
        {
            if (dc != null && dc.KnownDataContracts != null)
            {
                scopedKnownTypes.Push(dc.KnownDataContracts);
            }
        }
 
        internal void PopKnownTypes(DataContract dc)
        {
            if (dc != null && dc.KnownDataContracts != null)
            {
                scopedKnownTypes.Pop();
            }
        }
    }
}