SoapObjectWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / ManagedLibraries / SoapSerializer / SoapObjectWriter.cs / 1 / SoapObjectWriter.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//============================================================
// 
// Class: ObjectWriter 
//
// Author: Peter de Jong ([....]) 
//
// Purpose: Serializes an object graph into XML in SOAP format
//
// Date:  June 10, 1999 
//
//=========================================================== 
 
namespace System.Runtime.Serialization.Formatters.Soap
{ 
    using System;
    using System.IO;
    using System.Reflection;
    using System.Collections; 
    using System.Text;
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Messaging; 
    using System.Runtime.Remoting.Metadata;
    using System.Runtime.Remoting.Metadata.W3cXsd2001; 
    using System.Runtime.Serialization;
    using System.Security.Permissions;
    using System.Diagnostics;
    using System.Globalization; 

    internal sealed  class ObjectWriter 
    { 
        private Queue m_objectQueue;
        private ObjectIDGenerator m_idGenerator; 
        private Stream m_stream;
        private ISurrogateSelector m_surrogates;
        private StreamingContext m_context;
        private SoapWriter serWriter; 
        private SerializationObjectManager m_objectManager;
 
        //Keeps track of types written 
        // Null members are only written the first time for XML.
        private System.Collections.Hashtable m_serializedTypeTable; 

        private long topId;
        private String topName = null;
        private Header[] headers; 

        private InternalFE formatterEnums; 
 
        private SerObjectInfoInit serObjectInfoInit = null;
 
        private IFormatterConverter m_formatterConverter;

        // Default header name space
        private String headerNamespace = "http://schemas.microsoft.com/clr/soap"; 

        private bool bRemoting = false; 
 
        internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
 
        PrimitiveArray primitiveArray = null;

        // XMLObjectWriter Constructor
        internal ObjectWriter(Stream stream, ISurrogateSelector selector, StreamingContext context,InternalFE formatterEnums) 
        {
            if (stream==null) 
            { 
                throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream"));
            } 

            m_stream=stream;
            m_surrogates = selector;
            m_context = context; 
            this.formatterEnums = formatterEnums;
            m_objectManager = new SerializationObjectManager(context); 
            InternalST.InfoSoap( 
                               formatterEnums.FEtypeFormat +" "+
                               ((Enum)formatterEnums.FEserializerTypeEnum)); 

            m_formatterConverter = new FormatterConverter();

        } 

        // Commences the process of serializing the entire graph. 
        // initialize the graph walker. 
        internal void Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
        { 
            InternalST.Soap( this, "Serialize Entry 2 ",graph,((headers == null)?" no headers ": "headers"));

            serializationPermission.Demand();
 
            if (graph == null)
                throw new ArgumentNullException("graph",SoapUtil.GetResourceString("ArgumentNull_Graph")); 
 
            if (serWriter == null)
                throw new ArgumentNullException("serWriter",String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "serWriter")); 

            serObjectInfoInit = new SerObjectInfoInit();
            this.serWriter = serWriter;
            this.headers = inHeaders; 

            if (graph is IMethodMessage) 
            { 
                bRemoting = true;
                MethodBase methodBase = ((IMethodMessage)graph).MethodBase; 
                if (methodBase != null)
                    serWriter.WriteXsdVersion(ProcessTypeAttributes(methodBase.ReflectedType));
                else
                    serWriter.WriteXsdVersion(XsdVersion.V2001); 
            }
            else 
                serWriter.WriteXsdVersion(XsdVersion.V2001); 

            m_idGenerator = new ObjectIDGenerator(); 
            m_objectQueue = new Queue();

            if (graph is ISoapMessage)
            { 
                // Fake method call is to be written
                bRemoting = true; 
                ISoapMessage ismc = (ISoapMessage)graph; 
                graph = new InternalSoapMessage(ismc.MethodName, ismc.XmlNameSpace, ismc.ParamNames, ismc.ParamValues, ismc.ParamTypes);
                headers = ismc.Headers; 
            }


            InternalST.Soap( this, "Serialize New SerializedTypeTable"); 
            m_serializedTypeTable = new Hashtable();
 
            serWriter.WriteBegin(); 

            long headerId = 0; 
            Object obj;
            long objectId;
            bool isNew;
 
            topId = m_idGenerator.GetId(graph, out isNew);
 
            if (headers != null) 
                headerId = m_idGenerator.GetId(headers, out isNew);
            else 
                headerId = -1;

            WriteSerializedStreamHeader(topId, headerId);
 
            InternalST.Soap( this, "Serialize Schedule 0");
 
            // Write out SerializedStream header 
            if (!((headers == null) || (headers.Length == 0)))
            { 
                ProcessHeaders(headerId);
            }

            m_objectQueue.Enqueue(graph); 

            while ((obj = GetNext(out objectId))!=null) 
            { 
                InternalST.Soap( this, "Serialize GetNext ",obj);
                WriteObjectInfo objectInfo = null; 

                // GetNext will return either an object or a WriteObjectInfo.
                // A WriteObjectInfo is returned if this object was member of another object
                if (obj is WriteObjectInfo) 
                {
                    InternalST.Soap( this, "Serialize GetNext recognizes WriteObjectInfo"); 
                    objectInfo = (WriteObjectInfo)obj; 
                }
                else 
                {
                    objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null, this);
                    objectInfo.assemId = GetAssemblyId(objectInfo);
                } 

                objectInfo.objectId = objectId; 
                NameInfo typeNameInfo = TypeToNameInfo(objectInfo); 
                typeNameInfo.NIisTopLevelObject = true;
                if (bRemoting && obj  == graph) 
                    typeNameInfo.NIisRemoteRecord = true;
                Write(objectInfo, typeNameInfo, typeNameInfo);
                PutNameInfo(typeNameInfo);
                objectInfo.ObjectEnd(); 
            }
 
            serWriter.WriteSerializationHeaderEnd(); 
            serWriter.WriteEnd();
 
            m_idGenerator = new ObjectIDGenerator();
            InternalST.Soap( this, "*************Serialize New SerializedTypeTable 2");
            m_serializedTypeTable = new System.Collections.Hashtable();
 
            // Invoke OnSerialized Event
            m_objectManager.RaiseOnSerializedEvent(); 
 
            InternalST.Soap( this, "Serialize Exit ");
        } 

        private XsdVersion ProcessTypeAttributes(Type type)
        {
            // Check to see if the xsd and xsi schema types should be 1999 instead of 2000. This is a temporary fix for an interop problem 
            SoapTypeAttribute att = InternalRemotingServices.GetCachedSoapAttribute(type) as SoapTypeAttribute;
            XsdVersion xsdVersion = XsdVersion.V2001; 
            if (att != null) 
            {
                SoapOption soapOption = att.SoapOptions; 
                if ((soapOption &= SoapOption.Option1) == SoapOption.Option1)
                    xsdVersion = XsdVersion.V1999;
                else if ((soapOption &= SoapOption.Option1) == SoapOption.Option2)
                    xsdVersion = XsdVersion.V2000; 
            }
            return xsdVersion; 
        } 

        private void ProcessHeaders(long headerId) 
        {
            long objectId;
            Object obj;
 
            // XML Serializer
 
            serWriter.WriteHeader((int)headerId, headers.Length); 

            for (int i=0; i 0) 
                {
                    // Array as object 
                    InternalST.Soap( this, "WriteMembers Schedule 3");
                    memberNameInfo.NIobjectId = arrayId;
                    WriteObjectRef(memberNameInfo, memberTypeNameInfo, arrayId);
                } 
                else
                { 
                    // Nested Array 
                    serWriter.WriteMemberNested(memberNameInfo);
 
                    memberObjectInfo.objectId = arrayId;
                    memberNameInfo.NIobjectId = arrayId;
                    memberNameInfo.NIisNestedObject = true;
                    WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo); 
                }
                InternalST.Soap( this, "WriteMembers Array Exit "); 
                return; 
            }
 
            if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData, isAttribute))
            {
                InternalST.Soap( this, "WriteMembers Object ",memberData);
 
                // In soap an enum is written out as a string
                if (memberTypeNameInfo.NItype.IsEnum) 
                    WriteEnum(memberNameInfo, memberTypeNameInfo, memberData, isAttribute); 
                else
                { 

                    if (isAttribute)
                    {
                        // XmlAttribute must be a primitive type or string 
                        throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_NonPrimitive_XmlAttribute"), memberNameInfo.NIname));
                    } 
 
                    // Value or NO_ID, need to explicitly check for IsValue because a top level
                    // value class has an objectId of 1 
                    if ((memberType.IsValueType) || objectInfo.IsEmbeddedAttribute(memberNameInfo.NIname) || IsEmbeddedAttribute(outType))
                    {
                        InternalST.Soap( this, "WriteMembers Value Type or NO_ID parameter");
                        serWriter.WriteMemberNested(memberNameInfo); 

                        memberObjectInfo.objectId = -1; 
                        NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo); 
                        newTypeNameInfo.NIobjectId = -1;
                        memberNameInfo.NIisNestedObject = true; 
                        if (objectInfo.isSi)
                        {
                            memberTypeNameInfo.NItransmitTypeOnMember  = true;
                            memberNameInfo.NItransmitTypeOnMember  = true; 
                        }
                        Write( memberObjectInfo, memberNameInfo, newTypeNameInfo); 
                        PutNameInfo(newTypeNameInfo); 
                        memberObjectInfo.ObjectEnd();
                    } 
                    else
                    {
                        InternalST.Soap( this, "WriteMembers Schedule 4");
                        long memberObjectId = 0; 
                        memberObjectId = Schedule(outObj, outType, memberObjectInfo);
 
                        if (memberObjectId < 0) 
                        {
                            // Nested object 
                            InternalST.Soap( this, "WriteMembers Nesting");
                            serWriter.WriteMemberNested(memberNameInfo);

                            memberObjectInfo.objectId = -1; 
                            NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
                            newTypeNameInfo.NIobjectId = -1; 
                            memberNameInfo.NIisNestedObject = true; 
                            Write(memberObjectInfo, memberNameInfo, newTypeNameInfo);
                            PutNameInfo(newTypeNameInfo); 
                            memberObjectInfo.ObjectEnd();
                        }
                        else
                        { 
                            // Object reference
                            memberNameInfo.NIobjectId = memberObjectId; 
                            WriteObjectRef(memberNameInfo, memberTypeNameInfo, memberObjectId); 
                        }
                    } 
                }
            }

            InternalST.Soap( this, "WriteMembers Exit "); 
        }
 
        // Writes out an array 
        private void WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo)
        { 
            InternalST.Soap( this, "WriteArray Entry ",objectInfo.obj," ",objectInfo.objectId);

            bool isAllocatedMemberNameInfo = false;
            if (memberNameInfo == null) 
            {
                memberNameInfo = TypeToNameInfo(objectInfo); 
                memberNameInfo.NIisTopLevelObject = true; 
                isAllocatedMemberNameInfo = true;
            } 

            memberNameInfo.NIisArray = true;

            long objectId = objectInfo.objectId; 
            memberNameInfo.NIobjectId = objectInfo.objectId;
 
            // Get array type 
            System.Array array = (System.Array)objectInfo.obj;
            //Type arrayType = array.GetType(); 
            Type arrayType = objectInfo.objectType;

            // Get type of array element
            Type arrayElemType = arrayType.GetElementType(); 
            if (Nullable.GetUnderlyingType(arrayElemType) != null)
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_SoapNoGenericsSupport"), arrayElemType)); 
 
            WriteObjectInfo arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, (memberObjectInfo == null) ? null : memberObjectInfo.typeAttributeInfo);
            arrayElemObjectInfo.assemId = GetAssemblyId(arrayElemObjectInfo); 


            NameInfo arrayElemTypeNameInfo = null;
            NameInfo arrayNameInfo = ArrayTypeToNameInfo(objectInfo, out arrayElemTypeNameInfo); 
            arrayNameInfo.NIobjectId = objectId;
            arrayNameInfo.NIisArray = true; 
            arrayElemTypeNameInfo.NIobjectId = objectId; 
            arrayElemTypeNameInfo.NItransmitTypeOnMember = memberNameInfo.NItransmitTypeOnMember;
            arrayElemTypeNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject; 
            arrayElemTypeNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;

            // Get rank and length information
            int rank = array.Rank; 
            int[] lengthA = new int[rank];
            int[] lowerBoundA = new int[rank]; 
            int[] upperBoundA = new int[rank]; 
            for (int i=0; i-1; irank--) 
                {
                    // Find the current or lower dimension which can be incremented. 
                    if (currentA[irank] < maxA[irank]-1)
                    {
                        // The current dimension is at maximum. Increase the next lower dimension by 1
                        currentA[irank]++; 
                        if (irank < rank-1)
                        { 
                            // The current dimension and higher dimensions are zeroed. 
                            for (int i = irank+1; i 0) 
            {
                String elemBaseTypeString = arrayElemTypeName.Substring(0, arrayIndex); 
                InternalPrimitiveTypeE code = Converter.ToCode(elemBaseTypeString); 
                String convertedType = null;
                bool isConverted = false; 
                if (code != InternalPrimitiveTypeE.Invalid)
                {
                    if (code == InternalPrimitiveTypeE.Char)
                    { 
                        convertedType = elemBaseTypeString;
                        arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.UrtSystem; 
                    } 
                    else
                    { 
                        isConverted = true;
                        convertedType = Converter.ToXmlDataType(code);
                        String typeName = null;
                        arrayElemTypeNameInfo.NInameSpaceEnum = Converter.GetNameSpaceEnum(code, null, objectInfo, out typeName); 
                    }
                } 
                else 
                {
                    InternalST.Soap( this, "ArrayNameToDisplayName elemBaseTypeString ",elemBaseTypeString); 
                    if ((elemBaseTypeString.Equals("String")) || (elemBaseTypeString.Equals("System.String")))
                    {
                        isConverted = true;
                        convertedType = "string"; 
                        arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrString;
                    } 
                    else if (elemBaseTypeString.Equals("System.Object")) 
                    {
                        isConverted = true; 
                        convertedType = "anyType";
                        arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive;
                    }
                    else 
                    {
                        convertedType = elemBaseTypeString; 
                    } 
                }
 
                if (isConverted)
                {
                    arrayElemTypeNameInfo.NIname = convertedType+arrayElemTypeName.Substring(arrayIndex);
                } 
            }
            else if (arrayElemTypeName.Equals("System.Object")) 
            { 
                arrayElemTypeNameInfo.NIname = "anyType";
                arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive; 
            }

            InternalST.Soap( this, "ArrayNameToDisplayName Exit ",arrayElemTypeNameInfo.NIname);
        } 

        private Hashtable assemblyToIdTable = new Hashtable(20); 
        private StringBuilder sburi = new StringBuilder(50); 
        private long GetAssemblyId(WriteObjectInfo objectInfo)
        { 
            //use objectInfo to get assembly string with new criteria
            InternalST.Soap( this, "GetAssemblyId Entry ",objectInfo.objectType," isSi ",objectInfo.isSi);
            long assemId = 0;
            bool isNew = false; 
            String assemblyString = objectInfo.GetAssemblyString();
            String serializedAssemblyString = assemblyString; 
            if (assemblyString.Length == 0) 
            {
                // Fake type could returns an empty string 
                assemId = 0;
            }
            else if (assemblyString.Equals(Converter.urtAssemblyString))
            { 
                // Urt type is an assemId of 0. No assemblyString needs
                // to be sent but for soap, dotted names need to be placed in header 
                InternalST.Soap( this, "GetAssemblyId urt Assembly String "); 
                assemId = 0;
                isNew = false; 
                serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, null, (int)assemId, isNew, objectInfo.IsAttributeNameSpace());
            }
            else
            { 
                // Assembly needs to be sent
                // Need to prefix assembly string to separate the string names from the 
                // assemblyName string names. That is a string can have the same value 
                // as an assemblyNameString, but it is serialized differently
 
                if (assemblyToIdTable.ContainsKey(assemblyString))
                {
                    assemId = (long)assemblyToIdTable[assemblyString];
                    isNew = false; 
                }
                else 
                { 
                    assemId = m_idGenerator.GetId("___AssemblyString___"+assemblyString, out isNew);
                    assemblyToIdTable[assemblyString] = assemId; 
                }

                if (assemblyString != null && !objectInfo.IsInteropNameSpace())
                { 
                    if (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple)
                    { 
                        // Use only the simple assembly name (not version or strong name) 
                        int index = assemblyString.IndexOf(',');
                        if (index > 0) 
                            serializedAssemblyString = assemblyString.Substring(0, index);
                    }
                }
                serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, serializedAssemblyString, (int)assemId, isNew, objectInfo.IsInteropNameSpace()); 
            }
            InternalST.Soap( this, "GetAssemblyId Exit id ",assemId," isNew ",isNew," assemblyString ",serializedAssemblyString); 
            return assemId; 
        }
 
        private bool IsEmbeddedAttribute(Type type)
        {
            InternalST.Soap( this," IsEmbedded Entry ",type);
            bool isEmbedded = false; 
            if (type.IsValueType)
                isEmbedded = true; 
            else 
            {
                SoapTypeAttribute attr = (SoapTypeAttribute) 
                                         InternalRemotingServices.GetCachedSoapAttribute(type);
                isEmbedded = attr.Embedded;
            }
            InternalST.Soap( this," IsEmbedded Exit ",isEmbedded); 
            return isEmbedded;
        } 
 
        private void WriteEnum(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data, bool isAttribute)
        { 
            InternalST.Soap( this, "WriteEnum ", memberNameInfo.NIname," type ", typeNameInfo.NItype," data ",((Enum)data).ToString());
            // An enum is written out as a string
            if (isAttribute)
                serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, ((Enum)data).ToString()); 
            else
                serWriter.WriteMember(memberNameInfo, typeNameInfo, ((Enum)data).ToString()); 
        } 

        private Type GetType(Object obj) 
        {
            Type type = null;
            if (RemotingServices.IsTransparentProxy(obj))
                type = Converter.typeofMarshalByRefObject; 
            else
                type = obj.GetType(); 
            return type; 
        }
 
        private SerStack niPool = new SerStack("NameInfo Pool");

        private NameInfo GetNameInfo()
        { 
            NameInfo nameInfo = null;
 
            if (!niPool.IsEmpty()) 
            {
                nameInfo = (NameInfo)niPool.Pop(); 
                nameInfo.Init();
            }
            else
                nameInfo = new NameInfo(); 

            return nameInfo; 
        } 

        private bool CheckTypeFormat(FormatterTypeStyle test, FormatterTypeStyle want) 
        {
            return(test & want) == want;
        }
 
        private void PutNameInfo(NameInfo nameInfo)
        { 
            niPool.Push(nameInfo); 
        }
    } 

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//============================================================
// 
// Class: ObjectWriter 
//
// Author: Peter de Jong ([....]) 
//
// Purpose: Serializes an object graph into XML in SOAP format
//
// Date:  June 10, 1999 
//
//=========================================================== 
 
namespace System.Runtime.Serialization.Formatters.Soap
{ 
    using System;
    using System.IO;
    using System.Reflection;
    using System.Collections; 
    using System.Text;
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Messaging; 
    using System.Runtime.Remoting.Metadata;
    using System.Runtime.Remoting.Metadata.W3cXsd2001; 
    using System.Runtime.Serialization;
    using System.Security.Permissions;
    using System.Diagnostics;
    using System.Globalization; 

    internal sealed  class ObjectWriter 
    { 
        private Queue m_objectQueue;
        private ObjectIDGenerator m_idGenerator; 
        private Stream m_stream;
        private ISurrogateSelector m_surrogates;
        private StreamingContext m_context;
        private SoapWriter serWriter; 
        private SerializationObjectManager m_objectManager;
 
        //Keeps track of types written 
        // Null members are only written the first time for XML.
        private System.Collections.Hashtable m_serializedTypeTable; 

        private long topId;
        private String topName = null;
        private Header[] headers; 

        private InternalFE formatterEnums; 
 
        private SerObjectInfoInit serObjectInfoInit = null;
 
        private IFormatterConverter m_formatterConverter;

        // Default header name space
        private String headerNamespace = "http://schemas.microsoft.com/clr/soap"; 

        private bool bRemoting = false; 
 
        internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
 
        PrimitiveArray primitiveArray = null;

        // XMLObjectWriter Constructor
        internal ObjectWriter(Stream stream, ISurrogateSelector selector, StreamingContext context,InternalFE formatterEnums) 
        {
            if (stream==null) 
            { 
                throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream"));
            } 

            m_stream=stream;
            m_surrogates = selector;
            m_context = context; 
            this.formatterEnums = formatterEnums;
            m_objectManager = new SerializationObjectManager(context); 
            InternalST.InfoSoap( 
                               formatterEnums.FEtypeFormat +" "+
                               ((Enum)formatterEnums.FEserializerTypeEnum)); 

            m_formatterConverter = new FormatterConverter();

        } 

        // Commences the process of serializing the entire graph. 
        // initialize the graph walker. 
        internal void Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
        { 
            InternalST.Soap( this, "Serialize Entry 2 ",graph,((headers == null)?" no headers ": "headers"));

            serializationPermission.Demand();
 
            if (graph == null)
                throw new ArgumentNullException("graph",SoapUtil.GetResourceString("ArgumentNull_Graph")); 
 
            if (serWriter == null)
                throw new ArgumentNullException("serWriter",String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "serWriter")); 

            serObjectInfoInit = new SerObjectInfoInit();
            this.serWriter = serWriter;
            this.headers = inHeaders; 

            if (graph is IMethodMessage) 
            { 
                bRemoting = true;
                MethodBase methodBase = ((IMethodMessage)graph).MethodBase; 
                if (methodBase != null)
                    serWriter.WriteXsdVersion(ProcessTypeAttributes(methodBase.ReflectedType));
                else
                    serWriter.WriteXsdVersion(XsdVersion.V2001); 
            }
            else 
                serWriter.WriteXsdVersion(XsdVersion.V2001); 

            m_idGenerator = new ObjectIDGenerator(); 
            m_objectQueue = new Queue();

            if (graph is ISoapMessage)
            { 
                // Fake method call is to be written
                bRemoting = true; 
                ISoapMessage ismc = (ISoapMessage)graph; 
                graph = new InternalSoapMessage(ismc.MethodName, ismc.XmlNameSpace, ismc.ParamNames, ismc.ParamValues, ismc.ParamTypes);
                headers = ismc.Headers; 
            }


            InternalST.Soap( this, "Serialize New SerializedTypeTable"); 
            m_serializedTypeTable = new Hashtable();
 
            serWriter.WriteBegin(); 

            long headerId = 0; 
            Object obj;
            long objectId;
            bool isNew;
 
            topId = m_idGenerator.GetId(graph, out isNew);
 
            if (headers != null) 
                headerId = m_idGenerator.GetId(headers, out isNew);
            else 
                headerId = -1;

            WriteSerializedStreamHeader(topId, headerId);
 
            InternalST.Soap( this, "Serialize Schedule 0");
 
            // Write out SerializedStream header 
            if (!((headers == null) || (headers.Length == 0)))
            { 
                ProcessHeaders(headerId);
            }

            m_objectQueue.Enqueue(graph); 

            while ((obj = GetNext(out objectId))!=null) 
            { 
                InternalST.Soap( this, "Serialize GetNext ",obj);
                WriteObjectInfo objectInfo = null; 

                // GetNext will return either an object or a WriteObjectInfo.
                // A WriteObjectInfo is returned if this object was member of another object
                if (obj is WriteObjectInfo) 
                {
                    InternalST.Soap( this, "Serialize GetNext recognizes WriteObjectInfo"); 
                    objectInfo = (WriteObjectInfo)obj; 
                }
                else 
                {
                    objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null, this);
                    objectInfo.assemId = GetAssemblyId(objectInfo);
                } 

                objectInfo.objectId = objectId; 
                NameInfo typeNameInfo = TypeToNameInfo(objectInfo); 
                typeNameInfo.NIisTopLevelObject = true;
                if (bRemoting && obj  == graph) 
                    typeNameInfo.NIisRemoteRecord = true;
                Write(objectInfo, typeNameInfo, typeNameInfo);
                PutNameInfo(typeNameInfo);
                objectInfo.ObjectEnd(); 
            }
 
            serWriter.WriteSerializationHeaderEnd(); 
            serWriter.WriteEnd();
 
            m_idGenerator = new ObjectIDGenerator();
            InternalST.Soap( this, "*************Serialize New SerializedTypeTable 2");
            m_serializedTypeTable = new System.Collections.Hashtable();
 
            // Invoke OnSerialized Event
            m_objectManager.RaiseOnSerializedEvent(); 
 
            InternalST.Soap( this, "Serialize Exit ");
        } 

        private XsdVersion ProcessTypeAttributes(Type type)
        {
            // Check to see if the xsd and xsi schema types should be 1999 instead of 2000. This is a temporary fix for an interop problem 
            SoapTypeAttribute att = InternalRemotingServices.GetCachedSoapAttribute(type) as SoapTypeAttribute;
            XsdVersion xsdVersion = XsdVersion.V2001; 
            if (att != null) 
            {
                SoapOption soapOption = att.SoapOptions; 
                if ((soapOption &= SoapOption.Option1) == SoapOption.Option1)
                    xsdVersion = XsdVersion.V1999;
                else if ((soapOption &= SoapOption.Option1) == SoapOption.Option2)
                    xsdVersion = XsdVersion.V2000; 
            }
            return xsdVersion; 
        } 

        private void ProcessHeaders(long headerId) 
        {
            long objectId;
            Object obj;
 
            // XML Serializer
 
            serWriter.WriteHeader((int)headerId, headers.Length); 

            for (int i=0; i 0) 
                {
                    // Array as object 
                    InternalST.Soap( this, "WriteMembers Schedule 3");
                    memberNameInfo.NIobjectId = arrayId;
                    WriteObjectRef(memberNameInfo, memberTypeNameInfo, arrayId);
                } 
                else
                { 
                    // Nested Array 
                    serWriter.WriteMemberNested(memberNameInfo);
 
                    memberObjectInfo.objectId = arrayId;
                    memberNameInfo.NIobjectId = arrayId;
                    memberNameInfo.NIisNestedObject = true;
                    WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo); 
                }
                InternalST.Soap( this, "WriteMembers Array Exit "); 
                return; 
            }
 
            if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData, isAttribute))
            {
                InternalST.Soap( this, "WriteMembers Object ",memberData);
 
                // In soap an enum is written out as a string
                if (memberTypeNameInfo.NItype.IsEnum) 
                    WriteEnum(memberNameInfo, memberTypeNameInfo, memberData, isAttribute); 
                else
                { 

                    if (isAttribute)
                    {
                        // XmlAttribute must be a primitive type or string 
                        throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_NonPrimitive_XmlAttribute"), memberNameInfo.NIname));
                    } 
 
                    // Value or NO_ID, need to explicitly check for IsValue because a top level
                    // value class has an objectId of 1 
                    if ((memberType.IsValueType) || objectInfo.IsEmbeddedAttribute(memberNameInfo.NIname) || IsEmbeddedAttribute(outType))
                    {
                        InternalST.Soap( this, "WriteMembers Value Type or NO_ID parameter");
                        serWriter.WriteMemberNested(memberNameInfo); 

                        memberObjectInfo.objectId = -1; 
                        NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo); 
                        newTypeNameInfo.NIobjectId = -1;
                        memberNameInfo.NIisNestedObject = true; 
                        if (objectInfo.isSi)
                        {
                            memberTypeNameInfo.NItransmitTypeOnMember  = true;
                            memberNameInfo.NItransmitTypeOnMember  = true; 
                        }
                        Write( memberObjectInfo, memberNameInfo, newTypeNameInfo); 
                        PutNameInfo(newTypeNameInfo); 
                        memberObjectInfo.ObjectEnd();
                    } 
                    else
                    {
                        InternalST.Soap( this, "WriteMembers Schedule 4");
                        long memberObjectId = 0; 
                        memberObjectId = Schedule(outObj, outType, memberObjectInfo);
 
                        if (memberObjectId < 0) 
                        {
                            // Nested object 
                            InternalST.Soap( this, "WriteMembers Nesting");
                            serWriter.WriteMemberNested(memberNameInfo);

                            memberObjectInfo.objectId = -1; 
                            NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
                            newTypeNameInfo.NIobjectId = -1; 
                            memberNameInfo.NIisNestedObject = true; 
                            Write(memberObjectInfo, memberNameInfo, newTypeNameInfo);
                            PutNameInfo(newTypeNameInfo); 
                            memberObjectInfo.ObjectEnd();
                        }
                        else
                        { 
                            // Object reference
                            memberNameInfo.NIobjectId = memberObjectId; 
                            WriteObjectRef(memberNameInfo, memberTypeNameInfo, memberObjectId); 
                        }
                    } 
                }
            }

            InternalST.Soap( this, "WriteMembers Exit "); 
        }
 
        // Writes out an array 
        private void WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo)
        { 
            InternalST.Soap( this, "WriteArray Entry ",objectInfo.obj," ",objectInfo.objectId);

            bool isAllocatedMemberNameInfo = false;
            if (memberNameInfo == null) 
            {
                memberNameInfo = TypeToNameInfo(objectInfo); 
                memberNameInfo.NIisTopLevelObject = true; 
                isAllocatedMemberNameInfo = true;
            } 

            memberNameInfo.NIisArray = true;

            long objectId = objectInfo.objectId; 
            memberNameInfo.NIobjectId = objectInfo.objectId;
 
            // Get array type 
            System.Array array = (System.Array)objectInfo.obj;
            //Type arrayType = array.GetType(); 
            Type arrayType = objectInfo.objectType;

            // Get type of array element
            Type arrayElemType = arrayType.GetElementType(); 
            if (Nullable.GetUnderlyingType(arrayElemType) != null)
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_SoapNoGenericsSupport"), arrayElemType)); 
 
            WriteObjectInfo arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, (memberObjectInfo == null) ? null : memberObjectInfo.typeAttributeInfo);
            arrayElemObjectInfo.assemId = GetAssemblyId(arrayElemObjectInfo); 


            NameInfo arrayElemTypeNameInfo = null;
            NameInfo arrayNameInfo = ArrayTypeToNameInfo(objectInfo, out arrayElemTypeNameInfo); 
            arrayNameInfo.NIobjectId = objectId;
            arrayNameInfo.NIisArray = true; 
            arrayElemTypeNameInfo.NIobjectId = objectId; 
            arrayElemTypeNameInfo.NItransmitTypeOnMember = memberNameInfo.NItransmitTypeOnMember;
            arrayElemTypeNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject; 
            arrayElemTypeNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;

            // Get rank and length information
            int rank = array.Rank; 
            int[] lengthA = new int[rank];
            int[] lowerBoundA = new int[rank]; 
            int[] upperBoundA = new int[rank]; 
            for (int i=0; i-1; irank--) 
                {
                    // Find the current or lower dimension which can be incremented. 
                    if (currentA[irank] < maxA[irank]-1)
                    {
                        // The current dimension is at maximum. Increase the next lower dimension by 1
                        currentA[irank]++; 
                        if (irank < rank-1)
                        { 
                            // The current dimension and higher dimensions are zeroed. 
                            for (int i = irank+1; i 0) 
            {
                String elemBaseTypeString = arrayElemTypeName.Substring(0, arrayIndex); 
                InternalPrimitiveTypeE code = Converter.ToCode(elemBaseTypeString); 
                String convertedType = null;
                bool isConverted = false; 
                if (code != InternalPrimitiveTypeE.Invalid)
                {
                    if (code == InternalPrimitiveTypeE.Char)
                    { 
                        convertedType = elemBaseTypeString;
                        arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.UrtSystem; 
                    } 
                    else
                    { 
                        isConverted = true;
                        convertedType = Converter.ToXmlDataType(code);
                        String typeName = null;
                        arrayElemTypeNameInfo.NInameSpaceEnum = Converter.GetNameSpaceEnum(code, null, objectInfo, out typeName); 
                    }
                } 
                else 
                {
                    InternalST.Soap( this, "ArrayNameToDisplayName elemBaseTypeString ",elemBaseTypeString); 
                    if ((elemBaseTypeString.Equals("String")) || (elemBaseTypeString.Equals("System.String")))
                    {
                        isConverted = true;
                        convertedType = "string"; 
                        arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrString;
                    } 
                    else if (elemBaseTypeString.Equals("System.Object")) 
                    {
                        isConverted = true; 
                        convertedType = "anyType";
                        arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive;
                    }
                    else 
                    {
                        convertedType = elemBaseTypeString; 
                    } 
                }
 
                if (isConverted)
                {
                    arrayElemTypeNameInfo.NIname = convertedType+arrayElemTypeName.Substring(arrayIndex);
                } 
            }
            else if (arrayElemTypeName.Equals("System.Object")) 
            { 
                arrayElemTypeNameInfo.NIname = "anyType";
                arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive; 
            }

            InternalST.Soap( this, "ArrayNameToDisplayName Exit ",arrayElemTypeNameInfo.NIname);
        } 

        private Hashtable assemblyToIdTable = new Hashtable(20); 
        private StringBuilder sburi = new StringBuilder(50); 
        private long GetAssemblyId(WriteObjectInfo objectInfo)
        { 
            //use objectInfo to get assembly string with new criteria
            InternalST.Soap( this, "GetAssemblyId Entry ",objectInfo.objectType," isSi ",objectInfo.isSi);
            long assemId = 0;
            bool isNew = false; 
            String assemblyString = objectInfo.GetAssemblyString();
            String serializedAssemblyString = assemblyString; 
            if (assemblyString.Length == 0) 
            {
                // Fake type could returns an empty string 
                assemId = 0;
            }
            else if (assemblyString.Equals(Converter.urtAssemblyString))
            { 
                // Urt type is an assemId of 0. No assemblyString needs
                // to be sent but for soap, dotted names need to be placed in header 
                InternalST.Soap( this, "GetAssemblyId urt Assembly String "); 
                assemId = 0;
                isNew = false; 
                serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, null, (int)assemId, isNew, objectInfo.IsAttributeNameSpace());
            }
            else
            { 
                // Assembly needs to be sent
                // Need to prefix assembly string to separate the string names from the 
                // assemblyName string names. That is a string can have the same value 
                // as an assemblyNameString, but it is serialized differently
 
                if (assemblyToIdTable.ContainsKey(assemblyString))
                {
                    assemId = (long)assemblyToIdTable[assemblyString];
                    isNew = false; 
                }
                else 
                { 
                    assemId = m_idGenerator.GetId("___AssemblyString___"+assemblyString, out isNew);
                    assemblyToIdTable[assemblyString] = assemId; 
                }

                if (assemblyString != null && !objectInfo.IsInteropNameSpace())
                { 
                    if (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple)
                    { 
                        // Use only the simple assembly name (not version or strong name) 
                        int index = assemblyString.IndexOf(',');
                        if (index > 0) 
                            serializedAssemblyString = assemblyString.Substring(0, index);
                    }
                }
                serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, serializedAssemblyString, (int)assemId, isNew, objectInfo.IsInteropNameSpace()); 
            }
            InternalST.Soap( this, "GetAssemblyId Exit id ",assemId," isNew ",isNew," assemblyString ",serializedAssemblyString); 
            return assemId; 
        }
 
        private bool IsEmbeddedAttribute(Type type)
        {
            InternalST.Soap( this," IsEmbedded Entry ",type);
            bool isEmbedded = false; 
            if (type.IsValueType)
                isEmbedded = true; 
            else 
            {
                SoapTypeAttribute attr = (SoapTypeAttribute) 
                                         InternalRemotingServices.GetCachedSoapAttribute(type);
                isEmbedded = attr.Embedded;
            }
            InternalST.Soap( this," IsEmbedded Exit ",isEmbedded); 
            return isEmbedded;
        } 
 
        private void WriteEnum(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data, bool isAttribute)
        { 
            InternalST.Soap( this, "WriteEnum ", memberNameInfo.NIname," type ", typeNameInfo.NItype," data ",((Enum)data).ToString());
            // An enum is written out as a string
            if (isAttribute)
                serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, ((Enum)data).ToString()); 
            else
                serWriter.WriteMember(memberNameInfo, typeNameInfo, ((Enum)data).ToString()); 
        } 

        private Type GetType(Object obj) 
        {
            Type type = null;
            if (RemotingServices.IsTransparentProxy(obj))
                type = Converter.typeofMarshalByRefObject; 
            else
                type = obj.GetType(); 
            return type; 
        }
 
        private SerStack niPool = new SerStack("NameInfo Pool");

        private NameInfo GetNameInfo()
        { 
            NameInfo nameInfo = null;
 
            if (!niPool.IsEmpty()) 
            {
                nameInfo = (NameInfo)niPool.Pop(); 
                nameInfo.Init();
            }
            else
                nameInfo = new NameInfo(); 

            return nameInfo; 
        } 

        private bool CheckTypeFormat(FormatterTypeStyle test, FormatterTypeStyle want) 
        {
            return(test & want) == want;
        }
 
        private void PutNameInfo(NameInfo nameInfo)
        { 
            niPool.Push(nameInfo); 
        }
    } 

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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