XmlObjectSerializerWriteContextComplexJson.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Serialization / System / Runtime / Serialization / Json / XmlObjectSerializerWriteContextComplexJson.cs / 1305376 / XmlObjectSerializerWriteContextComplexJson.cs

                            using System; 
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection; 
using System.ServiceModel;
using System.Collections; 
 
namespace System.Runtime.Serialization.Json
{ 
#if USE_REFEMIT
 	public class XmlObjectSerializerWriteContextComplexJson : XmlObjectSerializerWriteContextComplex
#else
    internal class XmlObjectSerializerWriteContextComplexJson : XmlObjectSerializerWriteContextComplex 
#endif
    { 
        bool alwaysEmitXsiType; 
        bool perCallXsiTypeAlreadyEmitted;
 
        public XmlObjectSerializerWriteContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract)
            : base(serializer,
            serializer.MaxItemsInObjectGraph,
            new StreamingContext(StreamingContextStates.All), 
            serializer.IgnoreExtensionDataObject)
        { 
            this.alwaysEmitXsiType = serializer.AlwaysEmitTypeInformation; 
            this.rootTypeDataContract = rootTypeDataContract;
            this.serializerKnownTypeList = serializer.knownTypeList; 
            this.dataContractSurrogate = serializer.DataContractSurrogate;
        }

        internal static XmlObjectSerializerWriteContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract) 
        {
            return new XmlObjectSerializerWriteContextComplexJson(serializer, rootTypeDataContract); 
        } 

        internal IList SerializerKnownTypeList 
        {
            get
            {
                return this.serializerKnownTypeList; 
            }
        } 
 
        internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, string clrTypeName, string clrAssemblyName)
        { 
            return false;
        }

        internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, DataContract dataContract) 
        {
            return false; 
        } 

        internal override void WriteArraySize(XmlWriterDelegator xmlWriter, int size) 
        {
        }

        protected override void WriteTypeInfo(XmlWriterDelegator writer, string dataContractName, string dataContractNamespace) 
        {
            if (string.IsNullOrEmpty(dataContractNamespace)) 
            { 
                WriteTypeInfo(writer, dataContractName);
            } 
            else
            {
                WriteTypeInfo(writer, string.Concat(dataContractName, JsonGlobals.NameValueSeparatorString, TruncateDefaultDataContractNamespace(dataContractNamespace)));
            } 
        }
 
        internal static string TruncateDefaultDataContractNamespace(string dataContractNamespace) 
        {
            if (!string.IsNullOrEmpty(dataContractNamespace)) 
            {
                if (dataContractNamespace[0] == '#')
                {
                    return string.Concat("\\", dataContractNamespace); 
                }
                else if (dataContractNamespace[0] == '\\') 
                { 
                    return string.Concat("\\", dataContractNamespace);
                } 
                else if (dataContractNamespace.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal))
                {
                    return string.Concat("#", dataContractNamespace.Substring(JsonGlobals.DataContractXsdBaseNamespaceLength));
                } 
            }
 
            return dataContractNamespace; 
        }
 
        static bool RequiresJsonTypeInfo(DataContract contract)
        {
            return (contract is ClassDataContract);
        } 

        void WriteTypeInfo(XmlWriterDelegator writer, string typeInformation) 
        { 
            writer.WriteAttributeString(null, JsonGlobals.serverTypeString, null, typeInformation);
        } 

        protected override bool WriteTypeInfo(XmlWriterDelegator writer, DataContract contract, DataContract declaredContract)
        {
            if (!((object.ReferenceEquals(contract.Name, declaredContract.Name) && 
                   object.ReferenceEquals(contract.Namespace, declaredContract.Namespace)) ||
                 (contract.Name.Value == declaredContract.Name.Value && 
                 contract.Namespace.Value == declaredContract.Namespace.Value)) && 
                 (contract.UnderlyingType != Globals.TypeOfObjectArray))
            { 
                // We always deserialize collections assigned to System.Object as object[]
                // Because of its common and JSON-specific nature,
                //    we don't want to validate known type information for object[]
 
                if (RequiresJsonTypeInfo(contract))
                { 
                    perCallXsiTypeAlreadyEmitted = true; 
                    WriteTypeInfo(writer, contract.Name.Value, contract.Namespace.Value);
                } 
                else
                {
                    // check if the declared type is System.Enum and throw because
                    // __type information cannot be written for enums since it results in invalid JSON. 
                    // Without __type, the resulting JSON cannot be deserialized since a number cannot be directly assigned to System.Enum.
                    if (declaredContract.UnderlyingType == typeof(Enum)) 
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException
                            (SR.GetString(SR.EnumTypeNotSupportedByDataContractJsonSerializer, declaredContract.UnderlyingType))); 
                    }

                }
                // Return true regardless of whether we actually wrote __type information 
                // E.g. We don't write __type information for enums, but we still want verifyKnownType
                //      to be true for them. 
                return true; 
            }
            return false; 
        }


#if USE_REFEMIT 
        public void WriteJsonISerializable(XmlWriterDelegator xmlWriter, ISerializable obj)
#else 
        internal void WriteJsonISerializable(XmlWriterDelegator xmlWriter, ISerializable obj) 
#endif
        { 
            Type objType = obj.GetType();
            SerializationInfo serInfo = new SerializationInfo(objType, XmlObjectSerializer.FormatterConverter);
            obj.GetObjectData(serInfo, GetStreamingContext());
            if (DataContract.GetClrTypeFullName(objType) != serInfo.FullTypeName) 
            {
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ChangingFullTypeNameNotSupported, serInfo.FullTypeName, DataContract.GetClrTypeFullName(objType)))); 
            } 
            else
            { 
                base.WriteSerializationInfo(xmlWriter, objType, serInfo);
            }
        }
 

#if USE_REFEMIT 
        public static DataContract GetRevisedItemContract(DataContract oldItemContract) 
#else
        internal static DataContract GetRevisedItemContract(DataContract oldItemContract) 
#endif
        {
            if ((oldItemContract != null) &&
                oldItemContract.UnderlyingType.IsGenericType && 
                (oldItemContract.UnderlyingType.GetGenericTypeDefinition() == Globals.TypeOfKeyValue))
            { 
                return ClassDataContract.CreateClassDataContractForKeyValue(oldItemContract.UnderlyingType, oldItemContract.Namespace, new string[] { JsonGlobals.KeyString, JsonGlobals.ValueString }); 
            }
            return oldItemContract; 
        }

        protected override void WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle declaredTypeHandle)
        { 
            JsonDataContract jsonDataContract = JsonDataContract.GetJsonDataContract(dataContract);
            if (alwaysEmitXsiType && !perCallXsiTypeAlreadyEmitted && RequiresJsonTypeInfo(dataContract)) 
            { 
                WriteTypeInfo(xmlWriter, jsonDataContract.TypeName);
            } 
            perCallXsiTypeAlreadyEmitted = false;
            DataContractJsonSerializer.WriteJsonValue(jsonDataContract, xmlWriter, obj, this, declaredTypeHandle);
        }
 
        protected override void WriteNull(XmlWriterDelegator xmlWriter)
        { 
            DataContractJsonSerializer.WriteJsonNull(xmlWriter); 
        }
 
#if USE_REFEMIT
        public XmlDictionaryString CollectionItemName
#else
        internal XmlDictionaryString CollectionItemName 
#endif
        { 
            get { return JsonGlobals.itemDictionaryString; } 
        }
 
#if USE_REFEMIT
        public static void WriteJsonNameWithMapping(XmlWriterDelegator xmlWriter, XmlDictionaryString[] memberNames, int index)
#else
        internal static void WriteJsonNameWithMapping(XmlWriterDelegator xmlWriter, XmlDictionaryString[] memberNames, int index) 
#endif
        { 
            xmlWriter.WriteStartElement("a", JsonGlobals.itemString, JsonGlobals.itemString); 
            xmlWriter.WriteAttributeString(null, JsonGlobals.itemString, null, memberNames[index].Value);
        } 

        internal override void WriteExtensionDataTypeInfo(XmlWriterDelegator xmlWriter, IDataNode dataNode)
        {
            Type dataType = dataNode.DataType; 
            if (dataType == Globals.TypeOfClassDataNode ||
                dataType == Globals.TypeOfISerializableDataNode) 
            { 
                xmlWriter.WriteAttributeString(null, JsonGlobals.typeString, null, JsonGlobals.objectString);
                base.WriteExtensionDataTypeInfo(xmlWriter, dataNode); 
            }
            else if (dataType == Globals.TypeOfCollectionDataNode)
            {
                xmlWriter.WriteAttributeString(null, JsonGlobals.typeString, null, JsonGlobals.arrayString); 
                // Don't write __type for collections
            } 
            else if (dataType == Globals.TypeOfXmlDataNode) 
            {
                // Don't write type or __type for XML types because we serialize them to strings 
            }
            else if ((dataType == Globals.TypeOfObject) && (dataNode.Value != null))
            {
                DataContract dc = GetDataContract(dataNode.Value.GetType()); 
                if (RequiresJsonTypeInfo(dc))
                { 
                    base.WriteExtensionDataTypeInfo(xmlWriter, dataNode); 
                }
            } 
        }

        protected override void SerializeWithXsiType(XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
        { 
            DataContract dataContract;
            bool verifyKnownType = false; 
            bool isDeclaredTypeInterface = declaredType.IsInterface; 

            if (isDeclaredTypeInterface && CollectionDataContract.IsCollectionInterface(declaredType)) 
            {
                dataContract = GetDataContract(declaredTypeHandle, declaredType);
            }
            else if (declaredType.IsArray) // If declared type is array do not write __serverType. Instead write__serverType for each item 
            {
                dataContract = GetDataContract(declaredTypeHandle, declaredType); 
            } 
            else
            { 
                dataContract = GetDataContract(objectTypeHandle, objectType);
                DataContract declaredTypeContract = (declaredTypeID >= 0)
                    ? GetDataContract(declaredTypeID, declaredTypeHandle)
                    : GetDataContract(declaredTypeHandle, declaredType); 
                verifyKnownType = WriteTypeInfo(xmlWriter, dataContract, declaredTypeContract);
                HandleCollectionAssignedToObject(declaredType, ref dataContract, ref obj, ref verifyKnownType); 
            } 

            if (isDeclaredTypeInterface) 
            {
                VerifyObjectCompatibilityWithInterface(dataContract, obj, declaredType);
            }
            SerializeAndVerifyType(dataContract, xmlWriter, obj, verifyKnownType, declaredType.TypeHandle, declaredType); 
        }
 
        static void VerifyObjectCompatibilityWithInterface(DataContract contract, object graph, Type declaredType) 
        {
            Type contractType = contract.GetType(); 
            if ((contractType == typeof(XmlDataContract)) && !Globals.TypeOfIXmlSerializable.IsAssignableFrom(declaredType))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.XmlObjectAssignedToIncompatibleInterface, graph.GetType(), declaredType)));
            } 

            if ((contractType == typeof(CollectionDataContract)) && !CollectionDataContract.IsCollectionInterface(declaredType)) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.CollectionAssignedToIncompatibleInterface, graph.GetType(), declaredType)));
            } 
        }

        void HandleCollectionAssignedToObject(Type declaredType, ref DataContract dataContract, ref object obj, ref bool verifyKnownType)
        { 
            if ((declaredType != dataContract.UnderlyingType) && (dataContract is CollectionDataContract))
            { 
                if (verifyKnownType) 
                {
                    VerifyType(dataContract, declaredType); 
                    verifyKnownType = false;
                }
                if (((CollectionDataContract)dataContract).Kind == CollectionKind.Dictionary)
                { 
                    // Convert non-generic dictionary to generic dictionary
                    IDictionary dictionaryObj = obj as IDictionary; 
                    Dictionary genericDictionaryObj = new Dictionary(); 
                    foreach (DictionaryEntry entry in dictionaryObj)
                    { 
                        genericDictionaryObj.Add(entry.Key, entry.Value);
                    }
                    obj = genericDictionaryObj;
                } 
                dataContract = GetDataContract(Globals.TypeOfIEnumerable);
            } 
        } 

        internal override void SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType) 
        {
            bool verifyKnownType = false;
            Type declaredType = rootTypeDataContract.UnderlyingType;
            bool isDeclaredTypeInterface = declaredType.IsInterface; 

            if (!(isDeclaredTypeInterface && CollectionDataContract.IsCollectionInterface(declaredType)) 
                && !declaredType.IsArray)//Array covariance is not supported in XSD. If declared type is array do not write xsi:type. Instead write xsi:type for each item 
            {
                verifyKnownType = WriteTypeInfo(xmlWriter, dataContract, rootTypeDataContract); 
                HandleCollectionAssignedToObject(declaredType, ref dataContract, ref obj, ref verifyKnownType);
            }

            if (isDeclaredTypeInterface) 
            {
                VerifyObjectCompatibilityWithInterface(dataContract, obj, declaredType); 
            } 
            SerializeAndVerifyType(dataContract, xmlWriter, obj, verifyKnownType, declaredType.TypeHandle, declaredType);
        } 

        void VerifyType(DataContract dataContract, Type declaredType)
        {
            bool knownTypesAddedInCurrentScope = false; 
            if (dataContract.KnownDataContracts != null)
            { 
                scopedKnownTypes.Push(dataContract.KnownDataContracts); 
                knownTypesAddedInCurrentScope = true;
            } 

            if (!IsKnownType(dataContract, declaredType))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.DcTypeNotFoundOnSerialize, DataContract.GetClrTypeFullName(dataContract.UnderlyingType), dataContract.StableName.Name, dataContract.StableName.Namespace))); 
            }
 
            if (knownTypesAddedInCurrentScope) 
            {
                scopedKnownTypes.Pop(); 
            }
        }

        internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type) 
        {
            DataContract dataContract = base.GetDataContract(typeHandle, type); 
            DataContractJsonSerializer.CheckIfTypeIsReference(dataContract); 
            return dataContract;
        } 

        internal override DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
        {
            DataContract dataContract = base.GetDataContractSkipValidation(typeId, typeHandle, type); 
            DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
            return dataContract; 
        } 

        internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle) 
        {
            DataContract dataContract = base.GetDataContract(id, typeHandle);
            DataContractJsonSerializer.CheckIfTypeIsReference(dataContract);
            return dataContract; 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK