天天看點

ObjectWriter

  1. // ==++==
  2. // 
  3. //   
  4. //    Copyright (c) 2002 Microsoft Corporation.  All rights reserved.
  5. //   
  6. //    The use and distribution terms for this software are contained in the file
  7. //    named license.txt, which can be found in the root of this distribution.
  8. //    By using this software in any fashion, you are agreeing to be bound by the
  9. //    terms of this license.
  10. //   
  11. //    You must not remove this notice, or any other, from this software.
  12. //   
  13. // 
  14. // ==--==
  15. //============================================================
  16. //
  17. // Class: ObjectWriter
  18. // Purpose: Serializes an object graph into XML in SOAP format
  19. //
  20. // Date:  June 10, 1999
  21. //
  22. //============================================================
  23. namespace System.Runtime.Serialization.Formatters.Soap 
  24. {    
  25.     using System;
  26.     using System.IO;
  27.     using System.Reflection;
  28.     using System.Collections;
  29.     using System.Text;
  30.     using System.Runtime.Remoting;
  31.     using System.Runtime.Remoting.Messaging;    
  32.     using System.Runtime.Remoting.Metadata;
  33.     using System.Runtime.Remoting.Metadata.W3cXsd2001;
  34.     using System.Runtime.Serialization;
  35.     using System.Security.Permissions;
  36.     using System.Diagnostics;
  37.     internal sealed  class ObjectWriter
  38.     {
  39.         private Queue m_objectQueue;
  40.         private ObjectIDGenerator m_idGenerator;
  41.         private Stream m_stream;
  42.         private ISurrogateSelector m_surrogates;
  43.         private StreamingContext m_context;
  44.         private SoapWriter serWriter;
  45.         //Keeps track of types written
  46.         // Null members are only written the first time for XML.
  47.         private System.Collections.Hashtable m_serializedTypeTable;
  48.         private long topId;
  49.         private String topName = null;
  50.         private Header[] headers;
  51.         private InternalFE formatterEnums;
  52.         private SerObjectInfoInit serObjectInfoInit = null;
  53.         private IFormatterConverter m_formatterConverter;
  54.         // Default header name space
  55.         private String headerNamespace = "http://schemas.microsoft.com/clr/soap";
  56.         private bool bRemoting = false;
  57.         internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
  58.         PrimitiveArray primitiveArray = null;
  59.         // XMLObjectWriter Constructor
  60.         internal ObjectWriter(Stream stream, ISurrogateSelector selector, StreamingContext context,InternalFE formatterEnums)
  61.         {
  62.             if (stream==null)
  63.             {
  64.                 throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream"));               
  65.             }
  66.             m_stream=stream;
  67.             m_surrogates = selector;
  68.             m_context = context;
  69.             this.formatterEnums = formatterEnums;
  70.             InternalST.InfoSoap(
  71.                                formatterEnums.FEtypeFormat +" "+
  72.                                ((Enum)formatterEnums.FEserializerTypeEnum));
  73.             m_formatterConverter = new FormatterConverter();
  74.         }
  75.         // Commences the process of serializing the entire graph.
  76.         // initialize the graph walker.
  77.         internal void Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
  78.         {
  79.             InternalST.Soap( this, "Serialize Entry 2 ",graph,((headers == null)?" no headers ": "headers"));
  80.             serializationPermission.Demand();
  81.             if (graph == null)
  82.                 throw new ArgumentNullException("graph",SoapUtil.GetResourceString("ArgumentNull_Graph"));
  83.             if (serWriter == null)
  84.                 throw new ArgumentNullException("serWriter",String.Format(SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "serWriter"));
  85.             serObjectInfoInit = new SerObjectInfoInit();        
  86.             this.serWriter = serWriter;
  87.             this.headers = inHeaders;
  88.             if (graph is IMethodMessage)
  89.             {
  90.                 bRemoting = true;
  91.                 MethodBase methodBase = ((IMethodMessage)graph).MethodBase;
  92.                 if (methodBase != null)
  93.                     serWriter.WriteXsdVersion(ProcessTypeAttributes(methodBase.ReflectedType));
  94.                 else
  95.                     serWriter.WriteXsdVersion(XsdVersion.V2001);
  96.             }
  97.             else
  98.                 serWriter.WriteXsdVersion(XsdVersion.V2001);
  99.             m_idGenerator = new ObjectIDGenerator();
  100.             m_objectQueue = new Queue();
  101.             if (graph is ISoapMessage)
  102.             {
  103.                 // Fake method call is to be written
  104.                 bRemoting = true;
  105.                 ISoapMessage ismc = (ISoapMessage)graph;
  106.                 graph = new InternalSoapMessage(ismc.MethodName, ismc.XmlNameSpace, ismc.ParamNames, ismc.ParamValues, ismc.ParamTypes);
  107.                 headers = ismc.Headers;
  108.             }
  109.             InternalST.Soap( this, "Serialize New SerializedTypeTable");
  110.             m_serializedTypeTable = new Hashtable();
  111.             serWriter.WriteBegin();
  112.             long headerId = 0;
  113.             Object obj;
  114.             long objectId;
  115.             bool isNew;
  116.             topId = m_idGenerator.GetId(graph, out isNew);
  117.             if (headers != null)
  118.                 headerId = m_idGenerator.GetId(headers, out isNew);
  119.             else
  120.                 headerId = -1;
  121.             WriteSerializedStreamHeader(topId, headerId);
  122.             InternalST.Soap( this, "Serialize Schedule 0");
  123.             // Write out SerializedStream header
  124.             if (!((headers == null) || (headers.Length == 0)))
  125.             {
  126.                 ProcessHeaders(headerId);
  127.             }
  128.             m_objectQueue.Enqueue(graph);
  129.             while ((obj = GetNext(out objectId))!=null)
  130.             {
  131.                 InternalST.Soap( this, "Serialize GetNext ",obj);
  132.                 WriteObjectInfo objectInfo = null;
  133.                 // GetNext will return either an object or a WriteObjectInfo. 
  134.                 // A WriteObjectInfo is returned if this object was member of another object
  135.                 if (obj is WriteObjectInfo)
  136.                 {
  137.                     InternalST.Soap( this, "Serialize GetNext recognizes WriteObjectInfo");
  138.                     objectInfo = (WriteObjectInfo)obj;
  139.                 }
  140.                 else
  141.                 {
  142.                     objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
  143.                     objectInfo.assemId = GetAssemblyId(objectInfo);
  144.                 }
  145.                 objectInfo.objectId = objectId;
  146.                 NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
  147.                 typeNameInfo.NIisTopLevelObject = true;
  148.                 if (bRemoting && obj  == graph)
  149.                     typeNameInfo.NIisRemoteRecord = true;
  150.                 Write(objectInfo, typeNameInfo, typeNameInfo);
  151.                 PutNameInfo(typeNameInfo);
  152.                 objectInfo.ObjectEnd();
  153.             }
  154.             serWriter.WriteSerializationHeaderEnd();
  155.             serWriter.WriteEnd();
  156.             m_idGenerator = new ObjectIDGenerator();
  157.             InternalST.Soap( this, "*************Serialize New SerializedTypeTable 2");
  158.             m_serializedTypeTable = new System.Collections.Hashtable();
  159.             InternalST.Soap( this, "Serialize Exit ");
  160.         }
  161.         private XsdVersion ProcessTypeAttributes(Type type)
  162.         {
  163.             // 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
  164.             SoapTypeAttribute att = InternalRemotingServices.GetCachedSoapAttribute(type) as SoapTypeAttribute;
  165.             XsdVersion xsdVersion = XsdVersion.V2001;
  166.             if (att != null)
  167.             {
  168.                 SoapOption soapOption = att.SoapOptions;
  169.                 if ((soapOption &= SoapOption.Option1) == SoapOption.Option1)
  170.                     xsdVersion = XsdVersion.V1999;
  171.                 else if ((soapOption &= SoapOption.Option1) == SoapOption.Option2)
  172.                     xsdVersion = XsdVersion.V2000;
  173.             }
  174.             return xsdVersion;
  175.         }
  176.         private void ProcessHeaders(long headerId)
  177.         {
  178.             long objectId;
  179.             Object obj;
  180.             // XML Serializer
  181.             serWriter.WriteHeader((int)headerId, headers.Length);
  182.             for (int i=0; i<headers.Length; i++)
  183.             {
  184.                 Type headerValueType = null;
  185.                 if (headers[i].Value != null)
  186.                     headerValueType = GetType(headers[i].Value);
  187.                 if ((headerValueType != null) && (headerValueType == Converter.typeofString))
  188.                 {
  189.                     NameInfo nameInfo = GetNameInfo();
  190.                     nameInfo.NInameSpaceEnum = InternalNameSpaceE.UserNameSpace;
  191.                     nameInfo.NIname = headers[i].Name;
  192.                     nameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
  193.                     nameInfo.NIobjectId = -1;
  194.                     // Header will need to add a name space field which will if it doesn't the following
  195.                     // is the default name space
  196.                     HeaderNamespace(headers[i], nameInfo);
  197.                     serWriter.WriteHeaderString(nameInfo, headers[i].Value.ToString());
  198.                     PutNameInfo(nameInfo);
  199.                 }
  200.                 else if (headers[i].Name.Equals("__MethodSignature"))
  201.                 {
  202.                     InternalST.Soap( this, "Serialize Write Header __MethodSignature ");                        
  203.                     // Process message signature
  204.                     if (!(headers[i].Value is Type[]))
  205.                         throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_MethodSignature"), headerValueType));
  206.                     // Replace type array with an array of TypeToNameInfo's
  207.                     Type[] types = (Type[])headers[i].Value;
  208.                     NameInfo[] typeToNameInfos = new NameInfo[types.Length];
  209.                     WriteObjectInfo[] objectInfos = new WriteObjectInfo[types.Length];
  210.                     for (int j=0; j< types.Length; j++)
  211.                     {
  212.                         objectInfos[j] = WriteObjectInfo.Serialize(types[j], m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
  213.                         objectInfos[j].objectId = -1;
  214.                         objectInfos[j].assemId = GetAssemblyId(objectInfos[j]);                             
  215.                         typeToNameInfos[j] = TypeToNameInfo(objectInfos[j]);
  216.                     }
  217.                     // Create MemberNameInfo 
  218.                     NameInfo memberNameInfo = MemberToNameInfo(headers[i].Name);
  219.                     memberNameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
  220.                     memberNameInfo.NItransmitTypeOnMember = true;
  221.                     memberNameInfo.NIisNestedObject = true;
  222.                     memberNameInfo.NIisHeader = true;
  223.                     HeaderNamespace(headers[i], memberNameInfo);
  224.                     serWriter.WriteHeaderMethodSignature(memberNameInfo, typeToNameInfos);
  225.                     for (int j=0; j<types.Length; j++)
  226.                     {
  227.                         PutNameInfo(typeToNameInfos[j]);
  228.                         objectInfos[j].ObjectEnd();
  229.                     }
  230.                     PutNameInfo(memberNameInfo);
  231.                 }
  232.                 else
  233.                 {
  234.                     InternalPrimitiveTypeE code = InternalPrimitiveTypeE.Invalid;
  235.                     long valueId;
  236.                     if (headerValueType != null)
  237.                         code = Converter.ToCode(headerValueType);
  238.                     if ((headerValueType != null) && (code == InternalPrimitiveTypeE.Invalid))
  239.                     {
  240.                         // Object reference
  241.                         InternalST.Soap( this, "Serialize Schedule 2");
  242.                         valueId = Schedule(headers[i].Value, headerValueType);
  243.                         if (valueId == -1)
  244.                         {
  245.                             WriteObjectInfo objectInfo = WriteObjectInfo.Serialize(headers[i].Value, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
  246.                             objectInfo.objectId = -1;
  247.                             objectInfo.assemId = GetAssemblyId(objectInfo);                             
  248.                             NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
  249.                             NameInfo memberNameInfo = MemberToNameInfo(headers[i].Name);
  250.                             memberNameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
  251.                             memberNameInfo.NItransmitTypeOnMember = true;
  252.                             memberNameInfo.NIisNestedObject = true;
  253.                             memberNameInfo.NIisHeader = true;
  254.                             HeaderNamespace(headers[i], memberNameInfo);
  255.                             Write(objectInfo, memberNameInfo, typeNameInfo);
  256.                             PutNameInfo(typeNameInfo);
  257.                             PutNameInfo(memberNameInfo);
  258.                             objectInfo.ObjectEnd();
  259.                         }
  260.                         InternalST.Soap( this, "Serialize Write Header Object Reference ");
  261.                         NameInfo refNameInfo = MemberToNameInfo(headers[i].Name);
  262.                         refNameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
  263.                         refNameInfo.NIobjectId = valueId;
  264.                         refNameInfo.NItransmitTypeOnMember = true;
  265.                         refNameInfo.NIisNestedObject = true;                                                                                    
  266.                         HeaderNamespace(headers[i], refNameInfo);
  267.                         serWriter.WriteHeaderObjectRef(refNameInfo);
  268.                         PutNameInfo(refNameInfo);
  269.                     }
  270.                     else
  271.                     {
  272.                         // Primitive type or null                    
  273.                         InternalST.Soap( this, "Serialize Write Header primitive type ");
  274.                         NameInfo nameInfo = GetNameInfo();
  275.                         nameInfo.NInameSpaceEnum = InternalNameSpaceE.UserNameSpace;
  276.                         nameInfo.NIname = headers[i].Name;
  277.                         nameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
  278.                         nameInfo.NIprimitiveTypeEnum = code;
  279.                         // Header will need to add a name space field which will if it doesn't the following
  280.                         // is the default name space
  281.                         HeaderNamespace(headers[i], nameInfo);
  282.                         NameInfo typeNameInfo = null;
  283.                         if (headerValueType != null)
  284.                         {
  285.                             typeNameInfo = TypeToNameInfo(headerValueType);
  286.                             typeNameInfo.NItransmitTypeOnMember = true;
  287.                         }
  288.                         serWriter.WriteHeaderEntry(nameInfo, typeNameInfo, headers[i].Value);
  289.                         PutNameInfo(nameInfo);
  290.                         if (headerValueType != null)
  291.                             PutNameInfo(typeNameInfo);
  292.                     }
  293.                 }
  294.             }
  295.             serWriter.WriteHeaderArrayEnd();
  296.             // Serialize headers ahead of top graph
  297.             while ((obj = GetNext(out objectId))!=null)
  298.             {
  299.                 WriteObjectInfo objectInfo = null;
  300.                 // GetNext will return either an object or a WriteObjectInfo. 
  301.                 // A WriteObjectInfo is returned if this object was member of another object
  302.                 if (obj is WriteObjectInfo)
  303.                 {
  304.                     InternalST.Soap( this, "Serialize GetNext recognizes WriteObjectInfo");
  305.                     objectInfo = (WriteObjectInfo)obj;
  306.                 }
  307.                 else
  308.                 {
  309.                     objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
  310.                     objectInfo.assemId = GetAssemblyId(objectInfo);
  311.                 }
  312.                 objectInfo.objectId = objectId;
  313.                 NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
  314.                 Write(objectInfo, typeNameInfo, typeNameInfo);
  315.                 PutNameInfo(typeNameInfo);
  316.                 objectInfo.ObjectEnd();
  317.             }
  318.             serWriter.WriteHeaderSectionEnd();
  319.         }
  320.         private void HeaderNamespace(Header header, NameInfo nameInfo)
  321.         {
  322.             if (header.HeaderNamespace == null)
  323.                 nameInfo.NInamespace = headerNamespace;
  324.             else
  325.                 nameInfo.NInamespace = header.HeaderNamespace;
  326.             bool isNew = false;
  327.             nameInfo.NIheaderPrefix = "h"+InternalGetId(nameInfo.NInamespace, Converter.typeofString, out isNew);
  328.         }
  329.         // Writes a given object to the stream.
  330.         private void Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
  331.         {       
  332.             InternalST.Soap( this, "Write 1 Entry objectInfo ",objectInfo,", memberNameInfo ",memberNameInfo,", typeNameInfo ",typeNameInfo);
  333.             memberNameInfo.Dump("Write memberNameInfo");
  334.             typeNameInfo.Dump("Write typeNameInfo");
  335.             Object obj = objectInfo.obj;
  336.             if (obj==null)
  337.                 throw new ArgumentNullException("objectInfo.obj", String.Format(SoapUtil.GetResourceString("Serialization_ArgumentNull_Obj"), objectInfo.objectType));
  338.             Type objType = objectInfo.objectType;
  339.             long objectId = objectInfo.objectId;
  340.             InternalST.Soap( this, "Write 1 ",obj," ObjectId ",objectId);
  341.             if (objType == Converter.typeofString)
  342.             {
  343.                 // Top level String
  344.                 memberNameInfo.NIobjectId = objectId;
  345.                 serWriter.WriteObjectString(memberNameInfo, obj.ToString());
  346.             }
  347.             else if (objType == Converter.typeofTimeSpan)
  348.             {
  349.                 // Top level TimeSpan
  350.                 serWriter.WriteTopPrimitive(memberNameInfo, obj);
  351.             }
  352.             else
  353.             {
  354.                 if (objType.IsArray)
  355.                 {
  356.                     WriteArray(objectInfo, null, null); 
  357.                 }
  358.                 else
  359.                 {
  360.                     String[] memberNames;
  361.                     Type[] memberTypes;
  362.                     Object[] memberData;
  363.                     SoapAttributeInfo[] memberAttributeInfo;
  364.                     objectInfo.GetMemberInfo(out memberNames, out memberTypes, out memberData, out memberAttributeInfo);
  365.                     // Only Binary needs to transmit types for ISerializable because the binary formatter transmits the types in URT format.
  366.                     // Soap transmits all types as strings, so it is up to the ISerializable object to convert the string back to its URT type
  367.                     if (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))
  368.                     {
  369.                         InternalST.Soap( this, "Write 1 TransmitOnObject ");
  370.                         memberNameInfo.NItransmitTypeOnObject = true;
  371.                         memberNameInfo.NIisParentTypeOnObject = true;
  372.                         typeNameInfo.NItransmitTypeOnObject = true;
  373.                         typeNameInfo.NIisParentTypeOnObject = true;                                             
  374.                     }
  375.                     WriteObjectInfo[] memberObjectInfos = new WriteObjectInfo[memberNames.Length];
  376.                     // Get assembly information
  377.                     // Binary Serializer, assembly names need to be
  378.                     // written before objects are referenced.
  379.                     // GetAssemId here will write out the
  380.                     // assemblyStrings at the right Binary
  381.                     // Serialization object boundary.
  382.                     for (int i=0; i<memberTypes.Length; i++)
  383.                     {
  384.                         Type type = null;
  385.                         if (memberData[i] != null)                        
  386.                             type = GetType(memberData[i]);
  387.                         else
  388.                             type = typeof(Object);
  389.                         InternalPrimitiveTypeE code = Converter.ToCode(type);
  390.                         if ((code == InternalPrimitiveTypeE.Invalid && type != Converter.typeofString) ||
  391.                             ((objectInfo.cache.memberAttributeInfos != null) &
  392.                              (objectInfo.cache.memberAttributeInfos[i] != null) &
  393.                              ((objectInfo.cache.memberAttributeInfos[i].IsXmlAttribute()) ||
  394.                               (objectInfo.cache.memberAttributeInfos[i].IsXmlElement()))))
  395.                         {
  396.                             if (memberData[i] != null)
  397.                             {
  398.                                 memberObjectInfos[i] =
  399.                                 WriteObjectInfo.Serialize
  400.                                 (
  401.                                 memberData[i],
  402.                                 m_surrogates,
  403.                                 m_context,
  404.                                 serObjectInfoInit,
  405.                                 m_formatterConverter,
  406.                                 (memberAttributeInfo == null)? null : memberAttributeInfo[i]
  407.                                 );                                    
  408.                                 memberObjectInfos[i].assemId = GetAssemblyId(memberObjectInfos[i]);
  409.                             }
  410.                             else
  411.                             {
  412.                                 memberObjectInfos[i] =
  413.                                 WriteObjectInfo.Serialize
  414.                                 (
  415.                                 memberTypes[i],
  416.                                 m_surrogates,
  417.                                 m_context,
  418.                                 serObjectInfoInit,
  419.                                 m_formatterConverter,
  420.                                 ((memberAttributeInfo == null) ? null : memberAttributeInfo[i])
  421.                                 );
  422.                                 memberObjectInfos[i].assemId = GetAssemblyId(memberObjectInfos[i]);
  423.                             }
  424.                         }
  425.                     }
  426.                     Write(objectInfo, memberNameInfo, typeNameInfo, memberNames, memberTypes, memberData, memberObjectInfos);
  427.                 }
  428.                 InternalST.Soap( this, "Write 1 ",obj," type ",GetType(obj));
  429.                 // After first time null members do not have to be written        
  430.                 if (!(m_serializedTypeTable.ContainsKey(objType)))
  431.                 {
  432.                     InternalST.Soap( this, "Serialize SerializedTypeTable Add ",objType," obj ",obj);           
  433.                     m_serializedTypeTable.Add(objType, objType);
  434.                 }
  435.             }
  436.             InternalST.Soap( this, "Write 1 Exit ",obj);        
  437.         }
  438.         // Writes a given object to the stream.
  439.         private void Write(WriteObjectInfo objectInfo,         
  440.                            NameInfo memberNameInfo,          
  441.                            NameInfo typeNameInfo,            
  442.                            String[] memberNames,             
  443.                            Type[] memberTypes,               
  444.                            Object[] memberData,              
  445.                            WriteObjectInfo[] memberObjectInfos)
  446.         {
  447.             InternalST.Soap( this, "Write 2 Entry obj ",objectInfo.obj,". objectId ",objectInfo.objectId,", objType ",typeNameInfo.NIname,", memberName ",memberNameInfo.NIname,", memberType ",typeNameInfo.NIname,", isMustUnderstand ",memberNameInfo.NIisMustUnderstand);
  448.             int numItems = memberNames.Length;
  449.             NameInfo topNameInfo = null;
  450.             // Process members which will be written out as Soap attributes first
  451.             if (objectInfo.cache.memberAttributeInfos != null)
  452.             {
  453.                 InternalST.Soap( this, "Write Attribute Members");
  454.                 for (int i=0; i<objectInfo.cache.memberAttributeInfos.Length; i++)
  455.                 {
  456.                     InternalST.Soap( this, "Write Attribute Members name ", memberNames[i]);                    
  457.                     if ((objectInfo.cache.memberAttributeInfos[i] != null) &
  458.                         (objectInfo.cache.memberAttributeInfos[i].IsXmlAttribute()))
  459.                         WriteMemberSetup(objectInfo, memberNameInfo, typeNameInfo, memberNames[i], memberTypes[i], memberData[i], memberObjectInfos[i], true);
  460.                 }
  461.             }
  462.             if (memberNameInfo != null)
  463.             {
  464.                 InternalST.Soap( this, "Write 2 ObjectBegin, memberName ",memberNameInfo.NIname);
  465.                 memberNameInfo.NIobjectId = objectInfo.objectId;
  466.                 serWriter.WriteObject(memberNameInfo, typeNameInfo, numItems, memberNames, memberTypes, memberObjectInfos);
  467.             }
  468.             else if ((objectInfo.objectId == topId) && (topName != null))
  469.             {
  470.                 InternalST.Soap( this, "Write 2 ObjectBegin, topId method name ",topName);
  471.                 topNameInfo = MemberToNameInfo(topName);
  472.                 topNameInfo.NIobjectId = objectInfo.objectId;
  473.                 serWriter.WriteObject(topNameInfo, typeNameInfo, numItems, memberNames, memberTypes, memberObjectInfos);
  474.             }
  475.             else
  476.             {
  477.                 if (objectInfo.objectType != Converter.typeofString)
  478.                 {
  479.                     InternalST.Soap( this, "Write 2 ObjectBegin, default ", typeNameInfo.NIname);
  480.                     typeNameInfo.NIobjectId = objectInfo.objectId;
  481.                     serWriter.WriteObject(typeNameInfo, null, numItems, memberNames, memberTypes, memberObjectInfos);
  482.                 }
  483.             }
  484.             if (memberNameInfo.NIisParentTypeOnObject)
  485.             {
  486.                 memberNameInfo.NItransmitTypeOnObject = true;
  487.                 memberNameInfo.NIisParentTypeOnObject = false;
  488.             }
  489.             else
  490.                 memberNameInfo.NItransmitTypeOnObject = false;
  491.             // Write members
  492.             for (int i=0; i<numItems; i++)
  493.             {
  494.                 if ((objectInfo.cache.memberAttributeInfos == null) ||
  495.                     (objectInfo.cache.memberAttributeInfos[i] == null) ||
  496.                     (!(objectInfo.cache.memberAttributeInfos[i].IsXmlAttribute())))
  497.                     WriteMemberSetup(objectInfo, memberNameInfo, typeNameInfo, memberNames[i], memberTypes[i], memberData[i], memberObjectInfos[i], false);
  498.             }
  499.             if (memberNameInfo != null)
  500.             {
  501.                 memberNameInfo.NIobjectId = objectInfo.objectId;
  502.                 serWriter.WriteObjectEnd(memberNameInfo, typeNameInfo);
  503.             }
  504.             else if ((objectInfo.objectId == topId) && (topName != null))
  505.             {
  506.                 serWriter.WriteObjectEnd(topNameInfo, typeNameInfo);
  507.                 PutNameInfo(topNameInfo);
  508.             }
  509.             else
  510.             {
  511.                 if (objectInfo.objectType != Converter.typeofString)
  512.                 {
  513.                     String objectName = objectInfo.GetTypeFullName();
  514.                     serWriter.WriteObjectEnd(typeNameInfo, typeNameInfo);                       
  515.                 }
  516.             }
  517.             InternalST.Soap( this, "Write 2 Exit");
  518.         }
  519.         private void WriteMemberSetup(WriteObjectInfo objectInfo,      
  520.                                       NameInfo memberNameInfo,           
  521.                                       NameInfo typeNameInfo,             
  522.                                       String memberName,             
  523.                                       Type memberType,               
  524.                                       Object memberData,                 
  525.                                       WriteObjectInfo memberObjectInfo,
  526.                                       bool isAttribute
  527.                                      )
  528.         {
  529.             NameInfo newMemberNameInfo = MemberToNameInfo(memberName); 
  530.             // newMemberNameInfo contains the member type
  531.             if (memberObjectInfo != null)
  532.                 newMemberNameInfo.NIassemId = memberObjectInfo.assemId;
  533.             newMemberNameInfo.NItype = memberType;
  534.             // newTypeNameInfo contains the data type
  535.             NameInfo newTypeNameInfo = null;
  536.             if (memberObjectInfo == null)
  537.             {
  538.                 newTypeNameInfo = TypeToNameInfo(memberType);
  539.             }
  540.             else
  541.             {
  542.                 newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
  543.             }
  544.             newMemberNameInfo.NIisRemoteRecord = typeNameInfo.NIisRemoteRecord;
  545.             newMemberNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject;
  546.             newMemberNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;               
  547.             WriteMembers(newMemberNameInfo, newTypeNameInfo, memberData, objectInfo, typeNameInfo, memberObjectInfo, isAttribute);
  548.             PutNameInfo(newMemberNameInfo);
  549.             PutNameInfo(newTypeNameInfo);
  550.         }
  551.         // Writes the members of an object
  552.         private void WriteMembers(NameInfo memberNameInfo,
  553.                                   NameInfo memberTypeNameInfo,
  554.                                   Object   memberData,
  555.                                   WriteObjectInfo objectInfo,
  556.                                   NameInfo typeNameInfo,
  557.                                   WriteObjectInfo memberObjectInfo,
  558.                                   bool isAttribute)
  559.         {
  560.             InternalST.Soap( this, "WriteMembers Entry memberType: ",memberTypeNameInfo.NIname," memberName: ",memberNameInfo.NIname," data: ",memberData," objectId: ",objectInfo.objectId, " Container object ",objectInfo.obj, " isAttribute ", isAttribute);
  561.             Type memberType = memberNameInfo.NItype;
  562.             // Types are transmitted for a member as follows:
  563.             // The member is of type object
  564.             // The member object of type is ISerializable and
  565.             //        Soap -  the member is a non-primitive value type, or it is a primitive value type which needs types (TimeSpan, DateTime)
  566.             //                TimeSpan and DateTime are transmitted as UInt64 to keep their precision.
  567.             //      Binary - Types always transmitted.
  568.             if ((memberType == Converter.typeofObject) ||
  569.                 (memberType.IsValueType && objectInfo.isSi &
  570.                  Converter.IsSiTransmitType(memberTypeNameInfo.NIprimitiveTypeEnum)))
  571.             {
  572.                 memberTypeNameInfo.NItransmitTypeOnMember  = true;
  573.                 memberNameInfo.NItransmitTypeOnMember  = true;              
  574.             }
  575.             if (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))
  576.             {
  577.                 memberTypeNameInfo.NItransmitTypeOnObject  = true;
  578.                 memberNameInfo.NItransmitTypeOnObject  = true;
  579.                 memberNameInfo.NIisParentTypeOnObject = true;
  580.             }
  581.             if (CheckForNull(objectInfo, memberNameInfo, memberTypeNameInfo, memberData))
  582.             {
  583.                 return;
  584.             }
  585.             Object outObj = memberData;
  586.             Type outType = null;
  587.             // If member type does not equal data type, transmit type on object.
  588.             if (memberTypeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Invalid)
  589.             {
  590.                 if (RemotingServices.IsTransparentProxy(outObj))
  591.                     outType = Converter.typeofMarshalByRefObject;
  592.                 else
  593.                 {
  594.                     outType = GetType(outObj);
  595.                     if (memberType != outType)
  596.                     {
  597.                         memberTypeNameInfo.NItransmitTypeOnMember  = true;
  598.                         memberNameInfo.NItransmitTypeOnMember  = true;                              
  599.                     }
  600.                 }
  601.             }
  602.             if (memberType == Converter.typeofObject)
  603.             {
  604.                 memberType = GetType(memberData);
  605.                 if (memberObjectInfo == null)
  606.                     TypeToNameInfo(memberType, memberTypeNameInfo);
  607.                 else
  608.                     TypeToNameInfo(memberObjectInfo, memberTypeNameInfo);                   
  609.                 InternalST.Soap( this, "WriteMembers memberType Object, actual memberType ",memberType);                                                                                
  610.             }
  611.             if (memberObjectInfo != null && memberObjectInfo.isArray)
  612.             {
  613.                 // Array
  614.                 InternalST.Soap( this, "WriteMembers IsArray");
  615.                 long arrayId = 0;
  616.                 if (!(objectInfo.IsEmbeddedAttribute(memberNameInfo.NIname)|| IsEmbeddedAttribute(memberType)))
  617.                 {
  618.                     arrayId = Schedule(outObj, outType, memberObjectInfo);
  619.                 }
  620.                 if (arrayId > 0)
  621.                 {
  622.                     // Array as object
  623.                     InternalST.Soap( this, "WriteMembers Schedule 3");
  624.                     memberNameInfo.NIobjectId = arrayId;
  625.                     WriteObjectRef(memberNameInfo, arrayId); 
  626.                 }
  627.                 else
  628.                 {
  629.                     // Nested Array
  630.                     serWriter.WriteMemberNested(memberNameInfo);
  631.                     memberObjectInfo.objectId = arrayId;
  632.                     memberNameInfo.NIobjectId = arrayId;
  633.                     memberNameInfo.NIisNestedObject = true;
  634.                     WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo);
  635.                 }
  636.                 InternalST.Soap( this, "WriteMembers Array Exit ");
  637.                 return;
  638.             }
  639.             if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData, isAttribute))
  640.             {
  641.                 InternalST.Soap( this, "WriteMembers Object ",memberData);
  642.                 // In soap an enum is written out as a string
  643.                 if (memberTypeNameInfo.NItype.IsEnum)
  644.                     WriteEnum(memberNameInfo, memberTypeNameInfo, memberData, isAttribute);
  645.                 else
  646.                 {
  647.                     if (isAttribute)
  648.                     {
  649.                         // XmlAttribute must be a primitive type or string
  650.                         throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_NonPrimitive_XmlAttribute"), memberNameInfo.NIname));                                  
  651.                     }
  652.                     // Value or NO_ID, need to explicitly check for IsValue because a top level
  653.                     // value class has an objectId of 1
  654.                     if ((memberType.IsValueType) || objectInfo.IsEmbeddedAttribute(memberNameInfo.NIname) || IsEmbeddedAttribute(outType))
  655.                     {
  656.                         InternalST.Soap( this, "WriteMembers Value Type or NO_ID parameter");
  657.                         serWriter.WriteMemberNested(memberNameInfo);
  658.                         memberObjectInfo.objectId = -1;
  659.                         NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
  660.                         newTypeNameInfo.NIobjectId = -1;
  661.                         memberNameInfo.NIisNestedObject = true;
  662.                         if (objectInfo.isSi)
  663.                         {
  664.                             memberTypeNameInfo.NItransmitTypeOnMember  = true;
  665.                             memberNameInfo.NItransmitTypeOnMember  = true;                              
  666.                         }
  667.                         Write( memberObjectInfo, memberNameInfo, newTypeNameInfo);
  668.                         PutNameInfo(newTypeNameInfo);
  669.                         memberObjectInfo.ObjectEnd();
  670.                     }
  671.                     else
  672.                     {
  673.                         InternalST.Soap( this, "WriteMembers Schedule 4");
  674.                         long memberObjectId = 0;
  675.                         memberObjectId = Schedule(outObj, outType, memberObjectInfo);
  676.                         if (memberObjectId < 0)
  677.                         {
  678.                             // Nested object
  679.                             InternalST.Soap( this, "WriteMembers Nesting");
  680.                             serWriter.WriteMemberNested(memberNameInfo);
  681.                             memberObjectInfo.objectId = -1;
  682.                             NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
  683.                             newTypeNameInfo.NIobjectId = -1;
  684.                             memberNameInfo.NIisNestedObject = true;     
  685.                             Write(memberObjectInfo, memberNameInfo, newTypeNameInfo);
  686.                             PutNameInfo(newTypeNameInfo);
  687.                             memberObjectInfo.ObjectEnd();
  688.                         }
  689.                         else
  690.                         {
  691.                             // Object reference
  692.                             memberNameInfo.NIobjectId = memberObjectId;
  693.                             WriteObjectRef(memberNameInfo, memberObjectId); 
  694.                         }
  695.                     }
  696.                 }
  697.             }
  698.             InternalST.Soap( this, "WriteMembers Exit ");
  699.         }
  700.         // Writes out an array
  701.         private void WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo)          
  702.         {
  703.             InternalST.Soap( this, "WriteArray Entry ",objectInfo.obj," ",objectInfo.objectId);
  704.             bool isAllocatedMemberNameInfo = false;
  705.             if (memberNameInfo == null)
  706.             {
  707.                 memberNameInfo = TypeToNameInfo(objectInfo);
  708.                 memberNameInfo.NIisTopLevelObject = true;
  709.                 isAllocatedMemberNameInfo = true;
  710.             }
  711.             memberNameInfo.NIisArray = true;
  712.             long objectId = objectInfo.objectId;
  713.             memberNameInfo.NIobjectId = objectInfo.objectId;
  714.             // Get array type
  715.             System.Array array = (System.Array)objectInfo.obj;
  716.             //Type arrayType = array.GetType();
  717.             Type arrayType = objectInfo.objectType;         
  718.             // Get type of array element 
  719.             Type arrayElemType = arrayType.GetElementType();
  720.             WriteObjectInfo arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, (memberObjectInfo == null) ? null : memberObjectInfo.typeAttributeInfo);
  721.             arrayElemObjectInfo.assemId = GetAssemblyId(arrayElemObjectInfo);
  722.             NameInfo arrayElemTypeNameInfo = null;
  723.             NameInfo arrayNameInfo = ArrayTypeToNameInfo(objectInfo, out arrayElemTypeNameInfo);
  724.             arrayNameInfo.NIobjectId = objectId;
  725.             arrayNameInfo.NIisArray = true;
  726.             arrayElemTypeNameInfo.NIobjectId = objectId;
  727.             arrayElemTypeNameInfo.NItransmitTypeOnMember = memberNameInfo.NItransmitTypeOnMember;
  728.             arrayElemTypeNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject;
  729.             arrayElemTypeNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;
  730.             // Get rank and length information
  731.             int rank = array.Rank;
  732.             int[] lengthA = new int[rank];
  733.             int[] lowerBoundA = new int[rank];
  734.             int[] upperBoundA = new int[rank];                  
  735.             for (int i=0; i<rank; i++)
  736.             {
  737.                 lengthA[i] = array.GetLength(i);
  738.                 lowerBoundA[i] = array.GetLowerBound(i);
  739.                 upperBoundA[i] = array.GetUpperBound(i);                            
  740.             }
  741.             InternalArrayTypeE arrayEnum;
  742.             if (arrayElemType.IsArray)
  743.             {
  744.                 if (rank == 1)
  745.                     arrayEnum = InternalArrayTypeE.Jagged;
  746.                 else
  747.                     arrayEnum = InternalArrayTypeE.Rectangular;
  748.             }
  749.             else if (rank == 1)
  750.                 arrayEnum = InternalArrayTypeE.Single;
  751.             else
  752.                 arrayEnum = InternalArrayTypeE.Rectangular;
  753.             InternalST.Soap( this, "WriteArray ArrayInfo type ",arrayType," rank ",rank);
  754.             // Byte array
  755.             if ((arrayElemType == Converter.typeofByte) && (rank == 1) && (lowerBoundA[0] == 0))
  756.             {
  757.                 serWriter.WriteObjectByteArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0], (byte[])array);
  758.                 return;
  759.             }
  760.             if (arrayElemType == Converter.typeofObject)
  761.             {
  762.                 memberNameInfo.NItransmitTypeOnMember = true;
  763.                 arrayElemTypeNameInfo.NItransmitTypeOnMember = true;
  764.             }
  765.             if (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))
  766.             {
  767.                 memberNameInfo.NItransmitTypeOnObject = true;
  768.                 arrayElemTypeNameInfo.NItransmitTypeOnObject = true;                
  769.             }
  770.             if (arrayEnum == InternalArrayTypeE.Single)
  771.             {
  772.                 // Single Dimensional array
  773.                 InternalST.Soap( this, "WriteArray ARRAY_SINGLE ");
  774.                 arrayNameInfo.NIname = arrayElemTypeNameInfo.NIname+"["+lengthA[0]+"]";
  775.                 // BinaryFormatter array of primitive types is written out in the WriteSingleArray statement
  776.                 // as a byte buffer
  777.                 serWriter.WriteSingleArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0], array);
  778.                 if (Converter.IsWriteAsByteArray(arrayElemTypeNameInfo.NIprimitiveTypeEnum) && (lowerBoundA[0] == 0))
  779.                 {
  780.                     // If binaryformatter and array is of appopriate primitive type the array is
  781.                     // written out as a buffer of bytes. The array was transmitted in WriteSingleArray
  782.                     // If soap the index directly by array
  783.                     arrayElemTypeNameInfo.NIobjectId = 0;
  784.                     if (primitiveArray == null)
  785.                         primitiveArray = new PrimitiveArray(arrayElemTypeNameInfo.NIprimitiveTypeEnum, array);
  786.                     else
  787.                         primitiveArray.Init(arrayElemTypeNameInfo.NIprimitiveTypeEnum, array);
  788.                     int upperBound = upperBoundA[0]+1;                      
  789.                     for (int i = lowerBoundA[0]; i < upperBound; i++)
  790.                     {
  791.                         serWriter.WriteItemString(arrayElemTypeNameInfo, arrayElemTypeNameInfo, primitiveArray.GetValue(i));
  792.                     }
  793.                 }
  794.                 else
  795.                 {
  796.                     // Non-primitive type array
  797.                     Object[] objectA = null;
  798.                     if (!arrayElemType.IsValueType)
  799.                         objectA = (Object[])array;
  800.                     int upperBound = upperBoundA[0]+1;
  801.                     // Soap does not write out trailing nulls. lastValue is set to the last null value. This becomes the array's upperbound
  802.                     // Note: value classes can't be null
  803.                     if (objectA != null)
  804.                     {
  805.                         int lastValue = lowerBoundA[0]-1;
  806.                         for (int i = lowerBoundA[0]; i< upperBound; i++)
  807.                         {
  808.                             if (objectA[i] != null)
  809.                                 lastValue = i;
  810.                         }
  811.                         upperBound = lastValue+1;
  812.                     }
  813.                     for (int i = lowerBoundA[0]; i < upperBound; i++)
  814.                     {
  815.                         if (objectA == null)
  816.                             WriteArrayMember(objectInfo, arrayElemTypeNameInfo, array.GetValue(i));
  817.                         else
  818.                             WriteArrayMember(objectInfo, arrayElemTypeNameInfo, objectA[i]);
  819.                     }
  820.                 }
  821.             }
  822.             else if (arrayEnum == InternalArrayTypeE.Jagged)
  823.             {
  824.                 // Jagged Array
  825.                 InternalST.Soap( this, "WriteArray ARRAY_JAGGED");
  826.                 int index;
  827.                 String arrayElemTypeDimension = null;
  828.                 index = arrayNameInfo.NIname.IndexOf('[');
  829.                 if (index < 0)
  830.                     throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_Dimensions"),arrayElemTypeNameInfo.NIname));
  831.                 arrayElemTypeDimension = arrayNameInfo.NIname.Substring(index);
  832.                 InternalST.Soap( this, "WriteArray arrayNameInfo.NIname ",arrayNameInfo.NIname," arrayElemTypeNameInfo.NIname ",arrayElemTypeNameInfo.NIname," arrayElemTypeDimension ",arrayElemTypeDimension);
  833.                 arrayNameInfo.NIname = arrayElemTypeNameInfo.NIname+"["+lengthA[0]+"]";
  834.                 arrayNameInfo.NIobjectId = objectId;
  835.                 serWriter.WriteJaggedArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0]);
  836.                 Object[] objectA = (Object[])array;
  837.                 for (int i = lowerBoundA[0]; i < upperBoundA[0]+1; i++)
  838.                 {
  839.                     WriteArrayMember(objectInfo, arrayElemTypeNameInfo, objectA[i]);
  840.                 }
  841.             }
  842.             else
  843.             {
  844.                 // Rectangle Array
  845.                 // Get the length for all the ranks
  846.                 InternalST.Soap( this, "WriteArray ARRAY_RECTANGLE");                       
  847.                 // Express array Type using XmlData Name
  848.                 int index;
  849.                 index = arrayNameInfo.NIname.IndexOf('[');
  850.                 // Create length dimension string in form [3,4,2]
  851.                 StringBuilder sb = new StringBuilder(10);
  852.                 sb.Append(arrayElemTypeNameInfo.NIname);
  853.                 sb.Append('[');
  854.                 for (int i=0; i<rank; i++)
  855.                 {
  856.                     sb.Append(lengthA[i]);
  857.                     if (i < rank-1)
  858.                         sb.Append(',');
  859.                 }
  860.                 sb.Append(']');
  861.                 arrayNameInfo.NIname = sb.ToString();
  862.                 arrayNameInfo.NIobjectId = objectId;
  863.                 serWriter.WriteRectangleArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, rank, lengthA, lowerBoundA);
  864.                 IndexTraceMessage("WriteArray Rectangle  ", lengthA);
  865.                 bool bzero = false;
  866.                 for (int i=0; i<rank; i++)
  867.                 {
  868.                     if (lengthA[i] == 0)
  869.                     {
  870.                         bzero = true;
  871.                         break;
  872.                     }
  873.                 }
  874.                 if (!bzero)
  875.                     WriteRectangle(objectInfo, rank, lengthA, array, arrayElemTypeNameInfo, lowerBoundA);
  876.             }
  877.             serWriter.WriteObjectEnd(memberNameInfo, arrayNameInfo); 
  878.             PutNameInfo(arrayElemTypeNameInfo);
  879.             PutNameInfo(arrayNameInfo);
  880.             if (isAllocatedMemberNameInfo)
  881.                 PutNameInfo(memberNameInfo);
  882.             InternalST.Soap( this, "WriteArray Exit ");
  883.         }
  884.         // Writes out an array element
  885.         private void WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, Object data)
  886.         {
  887.             InternalST.Soap( this, "WriteArrayMember ",data," baseArrayName ",arrayElemTypeNameInfo.NIname);
  888.             arrayElemTypeNameInfo.NIisArrayItem = true;
  889.             if (CheckForNull(objectInfo, arrayElemTypeNameInfo, arrayElemTypeNameInfo, data))
  890.                 return;
  891.             NameInfo actualTypeInfo = null;
  892.             Type dataType = null;
  893.             bool isObjectOnMember = false;
  894.             if (arrayElemTypeNameInfo.NItransmitTypeOnMember)
  895.                 isObjectOnMember = true;
  896.             if (!isObjectOnMember && !arrayElemTypeNameInfo.NIisSealed)
  897.             {
  898.                 dataType = GetType(data);
  899.                 if (arrayElemTypeNameInfo.NItype != dataType)
  900.                     isObjectOnMember = true;
  901.             }
  902.             if (isObjectOnMember)
  903.             {
  904.                 // Object array, need type of member
  905.                 if (dataType == null)
  906.                     dataType = GetType(data);
  907.                 actualTypeInfo = TypeToNameInfo(dataType);
  908.                 actualTypeInfo.NItransmitTypeOnMember = true;
  909.                 actualTypeInfo.NIobjectId = arrayElemTypeNameInfo.NIobjectId;
  910.                 actualTypeInfo.NIassemId = arrayElemTypeNameInfo.NIassemId;
  911.                 actualTypeInfo.NIisArrayItem = true;
  912.                 actualTypeInfo.NIitemName = arrayElemTypeNameInfo.NIitemName;
  913.             }
  914.             else
  915.             {
  916.                 actualTypeInfo = arrayElemTypeNameInfo;
  917.                 actualTypeInfo.NIisArrayItem = true;
  918.             }
  919.             if (!WriteKnownValueClass(arrayElemTypeNameInfo, actualTypeInfo, data, false))
  920.             {
  921.                 Object obj = data;
  922.                 if (actualTypeInfo.NItype.IsEnum)
  923.                 {
  924.                     WriteObjectInfo newObjectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
  925.                     actualTypeInfo.NIassemId = GetAssemblyId(newObjectInfo);
  926.                     WriteEnum(arrayElemTypeNameInfo, actualTypeInfo, data, false);
  927.                 }
  928.                 else
  929.                 {
  930.                     long arrayId = Schedule(obj, actualTypeInfo.NItype);
  931.                     arrayElemTypeNameInfo.NIobjectId = arrayId;
  932.                     actualTypeInfo.NIobjectId = arrayId;
  933.                     if (arrayId < 1)
  934.                     {
  935.                         WriteObjectInfo newObjectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
  936.                         newObjectInfo.objectId = arrayId;
  937.                         newObjectInfo.assemId = GetAssemblyId(newObjectInfo);
  938.                         InternalST.Soap( this, "WriteArrayMembers nested");
  939.                         if (dataType == null)
  940.                             dataType = GetType(data);
  941.                         if (data!=null && dataType.IsArray)
  942.                         {
  943.                             WriteArray(newObjectInfo, actualTypeInfo, null);
  944.                         }
  945.                         else
  946.                         {
  947.                             actualTypeInfo.NIisNestedObject = true;
  948.                             NameInfo typeNameInfo = TypeToNameInfo(newObjectInfo);
  949.                             typeNameInfo.NIobjectId = arrayId;
  950.                             newObjectInfo.objectId = arrayId;
  951.                             Write(newObjectInfo, actualTypeInfo, typeNameInfo);
  952.                         }
  953.                         newObjectInfo.ObjectEnd();
  954.                     }
  955.                     else
  956.                         serWriter.WriteItemObjectRef(arrayElemTypeNameInfo, (int)arrayId);
  957.                 }
  958.             }
  959.             if (arrayElemTypeNameInfo.NItransmitTypeOnMember)
  960.                 PutNameInfo(actualTypeInfo);
  961.         }
  962.         // Iterates over a Rectangle array, for each element of the array invokes WriteArrayMember
  963.         private void WriteRectangle(WriteObjectInfo objectInfo, int rank, int[] maxA, System.Array array, NameInfo arrayElemNameTypeInfo, int[] lowerBoundA)
  964.         {
  965.             IndexTraceMessage("WriteRectangle  Entry "+rank, maxA);
  966.             int[] currentA = new int[rank];
  967.             int[] indexMap = null;
  968.             bool isLowerBound = false;
  969.             if (lowerBoundA != null)
  970.             {
  971.                 for (int i=0; i<rank; i++)
  972.                 {
  973.                     if (lowerBoundA[i] != 0)
  974.                         isLowerBound = true;
  975.                 }
  976.             }
  977.             if (isLowerBound)
  978.                 indexMap = new int[rank];
  979.             bool isLoop = true;
  980.             while (isLoop)
  981.             {
  982.                 isLoop = false;
  983.                 if (isLowerBound)
  984.                 {
  985.                     for (int i=0; i<rank; i++)
  986.                         indexMap[i] = currentA[i]+lowerBoundA[i];
  987.                     WriteArrayMember(objectInfo, arrayElemNameTypeInfo, array.GetValue(indexMap));
  988.                 }
  989.                 else
  990.                     WriteArrayMember(objectInfo, arrayElemNameTypeInfo, array.GetValue(currentA));          
  991.                 for (int irank = rank-1; irank>-1; irank--)
  992.                 {
  993.                     // Find the current or lower dimension which can be incremented.
  994.                     if (currentA[irank] < maxA[irank]-1)
  995.                     {
  996.                         // The current dimension is at maximum. Increase the next lower dimension by 1
  997.                         currentA[irank]++;
  998.                         if (irank < rank-1)
  999.                         {
  1000.                             // The current dimension and higher dimensions are zeroed.
  1001.                             for (int i = irank+1; i<rank; i++)
  1002.                                 currentA[i] = 0;
  1003.                         }
  1004.                         isLoop = true;
  1005.                         break;                  
  1006.                     }
  1007.                 }
  1008.             }
  1009.             InternalST.Soap( this, "WriteRectangle  Exit ");
  1010.         }
  1011.         // Traces a message with an array of int
  1012.         [Conditional("SER_LOGGING")]                            
  1013.         private void IndexTraceMessage(String message, int[] index)
  1014.         {
  1015.             StringBuilder sb = new StringBuilder(10);
  1016.             sb.Append("[");     
  1017.             for (int i=0; i<index.Length; i++)
  1018.             {
  1019.                 sb.Append(index[i]);
  1020.                 if (i != index.Length -1)
  1021.                     sb.Append(",");
  1022.             }
  1023.             sb.Append("]");             
  1024.             InternalST.Soap( this, message+" ",sb.ToString());
  1025.         }
  1026.         // This gives back the next object to be serialized.  Objects
  1027.         // are returned in a FIFO order based on how they were passed
  1028.         // to Schedule.  The id of the object is put into the objID parameter
  1029.         // and the Object itself is returned from the function.
  1030.         private Object GetNext(out long objID)
  1031.         {
  1032.             InternalST.Soap( this, "GetNext Entry ");       
  1033.             bool isNew;
  1034.             //The Queue is empty here.  We'll throw if we try to dequeue the empty queue.
  1035.             if (m_objectQueue.Count==0)
  1036.             {
  1037.                 objID=0;
  1038.                 InternalST.Soap( this, "GetNext Exit null");
  1039.                 return null;
  1040.             }
  1041.             Object obj = m_objectQueue.Dequeue();
  1042.             Object realObj = null;
  1043.             // A WriteObjectInfo is queued if this object was a member of another object
  1044.             InternalST.Soap( this, "GetNext ",obj);
  1045.             if (obj is WriteObjectInfo)
  1046.             {
  1047.                 InternalST.Soap( this, "GetNext recognizes WriteObjectInfo");
  1048.                 realObj = ((WriteObjectInfo)obj).obj;
  1049.             }
  1050.             else
  1051.                 realObj = obj;
  1052.             objID = m_idGenerator.HasId(realObj, out isNew);
  1053.             if (isNew)
  1054.             {
  1055.                 InternalST.Soap( this, "Object " , obj , " has never been assigned an id.");
  1056.                 throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_ObjNoID"),obj));                                                   
  1057.             }
  1058.             InternalST.Soap( this, "GetNext Exit "+objID," ",obj);              
  1059.             return obj;
  1060.         }
  1061.         Object previousObj = null;
  1062.         long previousId = 0;
  1063.         private long InternalGetId(Object obj, Type type, out bool isNew)
  1064.         {
  1065.             if (obj == previousObj)
  1066.             {
  1067.                 isNew = false;
  1068.                 return previousId;
  1069.             }
  1070.             if (type.IsValueType)
  1071.             {
  1072.                 isNew = false;
  1073.                 previousObj = obj;
  1074.                 previousId = -1;
  1075.                 return -1;
  1076.             }
  1077.             else
  1078.             {
  1079.                 long objectId = m_idGenerator.GetId(obj, out isNew);
  1080.                 previousObj = obj;
  1081.                 previousId = objectId;              
  1082.                 return objectId;
  1083.             }
  1084.         }
  1085.         // Schedules an object for later serialization if it hasn't already been scheduled.
  1086.         // We get an ID for obj and put it on the queue for later serialization
  1087.         // if this is a new object id.
  1088.         private long Schedule(Object obj, Type type)
  1089.         {
  1090.             return Schedule(obj, type, null);
  1091.         }
  1092.         private long Schedule(Object obj, Type type, WriteObjectInfo objectInfo)
  1093.         {
  1094.             InternalST.Soap( this, "Schedule Entry ",((obj == null)?"null":obj));
  1095.             bool isNew;
  1096.             long id;
  1097.             if (obj==null)
  1098.             {
  1099.                 InternalST.Soap(this, "Schedule Obj Null, id = 0 ");
  1100.                 return 0;
  1101.             }
  1102.             id = InternalGetId(obj, type, out isNew);           
  1103.             if (isNew)
  1104.             {
  1105.                 if (objectInfo == null)
  1106.                     m_objectQueue.Enqueue(obj);
  1107.                 else
  1108.                     m_objectQueue.Enqueue(objectInfo);
  1109.             }
  1110.             InternalST.Soap( this, "Schedule Exit, id: ",id," isNew: ",isNew);      
  1111.             return id;
  1112.         }
  1113.         // Determines if a type is a primitive type, if it is it is written
  1114.         private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data, bool isAttribute) 
  1115.         {
  1116.             InternalST.Soap( this, "WriteKnownValueClass Entry ",typeNameInfo.NIname," ",data," ",memberNameInfo.NIname);
  1117.             memberNameInfo.Dump("WriteKnownValueClass memberNameInfo");         
  1118.             typeNameInfo.Dump("WriteKnownValueClass typeNameInfo");
  1119.             if (typeNameInfo.NItype == Converter.typeofString)
  1120.             {
  1121.                 if (isAttribute)
  1122.                     serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, (String)data);
  1123.                 else
  1124.                     WriteString(memberNameInfo, typeNameInfo, data);
  1125.             }
  1126.             else
  1127.             {
  1128.                 if (typeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Invalid)
  1129.                 {
  1130.                     InternalST.Soap( this, "WriteKnownValueClass Exit false");                      
  1131.                     return false;
  1132.                 }
  1133.                 else
  1134.                 {
  1135.                     if (typeNameInfo.NIisArray) // null if an array
  1136.                         serWriter.WriteItem(memberNameInfo, typeNameInfo, data);
  1137.                     else
  1138.                     {
  1139.                         if (isAttribute)
  1140.                             serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, data);
  1141.                         else
  1142.                             serWriter.WriteMember(memberNameInfo, typeNameInfo, data);
  1143.                     }
  1144.                 }
  1145.             }
  1146.             InternalST.Soap( this, "WriteKnownValueClass Exit true");
  1147.             return true;
  1148.         }
  1149.         // Writes an object reference to the stream.
  1150.         private void WriteObjectRef(NameInfo nameInfo, long objectId)
  1151.         {
  1152.             InternalST.Soap( this, "WriteObjectRef Entry ",nameInfo.NIname," ",objectId);
  1153.             serWriter.WriteMemberObjectRef(nameInfo, (int)objectId);
  1154.             InternalST.Soap( this, "WriteObjectRef Exit ");
  1155.         }
  1156.         // Writes a string into the XML stream
  1157.         private void WriteString(NameInfo memberNameInfo, NameInfo typeNameInfo, Object stringObject)
  1158.         {
  1159.             InternalST.Soap( this, "WriteString stringObject ",stringObject," memberName ",memberNameInfo.NIname);
  1160.             bool isFirstTime = true;
  1161.             long stringId = -1;
  1162.             if (!CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.XsdString))
  1163.                 stringId= InternalGetId(stringObject, typeNameInfo.NItype, out isFirstTime);
  1164.             typeNameInfo.NIobjectId = stringId;
  1165.             InternalST.Soap( this, "WriteString stringId ",stringId," isFirstTime ",isFirstTime);
  1166.             if ((isFirstTime) || (stringId < 0))
  1167.             {
  1168.                 if (typeNameInfo.NIisArray) // null if array
  1169.                     serWriter.WriteItemString(memberNameInfo, typeNameInfo, (String)stringObject);
  1170.                 else
  1171.                     serWriter.WriteMemberString(memberNameInfo, typeNameInfo, (String)stringObject);
  1172.             }
  1173.             else
  1174.             {
  1175.                 WriteObjectRef(memberNameInfo, stringId);
  1176.             }
  1177.         }
  1178.         // Writes a null member into the stream
  1179.         private bool CheckForNull(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, Object data)
  1180.         {
  1181.             InternalST.Soap( this, "CheckForNull Entry data ",Util.PString(data),", memberType ",Util.PString(typeNameInfo.NItype));
  1182.             bool isNull = false;
  1183.             if (data == null) // || Convert.IsDBNull(data)
  1184.                 isNull = true;
  1185.             // Optimization, Null members are only written for Binary
  1186.             if (isNull)
  1187.             {
  1188.                 InternalST.Soap( this, "CheckForNull Write");
  1189.                 if (typeNameInfo.NItype.IsArray)
  1190.                 {
  1191.                     // Call can occur before typeNameInfo.NIisArray is set
  1192.                     ArrayNameToDisplayName(objectInfo, typeNameInfo);
  1193.                 }
  1194.                 if (typeNameInfo.NIisArrayItem)
  1195.                     serWriter.WriteNullItem(memberNameInfo, typeNameInfo);
  1196.                 else
  1197.                     serWriter.WriteNullMember(memberNameInfo, typeNameInfo);
  1198.             }
  1199.             InternalST.Soap( this, "CheckForNull Exit ",isNull);
  1200.             return isNull;
  1201.         }
  1202.         // Writes the SerializedStreamHeader
  1203.         private void WriteSerializedStreamHeader(long topId, long headerId)
  1204.         {
  1205.             serWriter.WriteSerializationHeader((int)topId, (int)headerId, 1, 0);
  1206.         }
  1207.         // Transforms a type to the serialized string form. URT Primitive types are converted to XMLData Types
  1208.         private NameInfo TypeToNameInfo(Type type, WriteObjectInfo objectInfo, InternalPrimitiveTypeE code, NameInfo nameInfo)
  1209.         {
  1210.             InternalST.Soap( this, "TypeToNameInfo Entry type ",type,", objectInfo ",objectInfo,", code ", ((Enum)code).ToString());
  1211.             if (nameInfo == null)
  1212.                 nameInfo = GetNameInfo();
  1213.             else
  1214.                 nameInfo.Init();
  1215.             nameInfo.NIisSealed = type.IsSealed;
  1216.             String typeName = null;
  1217.             nameInfo.NInameSpaceEnum = Converter.GetNameSpaceEnum(code, type, objectInfo, out typeName);
  1218.             nameInfo.NIprimitiveTypeEnum = code;
  1219.             nameInfo.NItype = type;
  1220.             nameInfo.NIname = typeName;
  1221.             if (objectInfo != null)
  1222.             {
  1223.                 nameInfo.NIattributeInfo = objectInfo.typeAttributeInfo;                    
  1224.                 nameInfo.NIassemId = objectInfo.assemId;
  1225.             }
  1226.             switch (nameInfo.NInameSpaceEnum)
  1227.             {
  1228.                 case InternalNameSpaceE.XdrPrimitive:
  1229.                     break;
  1230.                 case InternalNameSpaceE.XdrString:
  1231.                     nameInfo.NIname = "string";
  1232.                     break;
  1233.                 case InternalNameSpaceE.UrtSystem:
  1234.                     break;
  1235.                 case InternalNameSpaceE.UrtUser:
  1236.                     //if (type.FullName.StartsWith("System."))
  1237.                     if (type.Module.Assembly == Converter.urtAssembly)
  1238.                     {
  1239.                         // The type name could be an ISerializable
  1240.                         // But the type returned (typeName) could be a fake
  1241.                         // type
  1242.                     }
  1243.                     else
  1244.                     {
  1245.                         if (objectInfo == null)
  1246.                         {
  1247.                             InternalST.Soap( this, "TypeToNameInfo ObjectInfo is null 2 ",type);
  1248.                         }
  1249.                     }
  1250.                     break;
  1251.             }
  1252.             InternalST.Soap( this, "TypeToNameInfo Exit ",type, " typeName "+nameInfo.NIname);
  1253.             return nameInfo;            
  1254.         }
  1255.         private NameInfo TypeToNameInfo(Type type)
  1256.         {
  1257.             return TypeToNameInfo(type, null, Converter.ToCode(type), null);
  1258.         }
  1259.         private NameInfo TypeToNameInfo(Type type, InternalPrimitiveTypeE code)
  1260.         {
  1261.             return TypeToNameInfo(type, null, code, null);
  1262.         }
  1263.         private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo)
  1264.         {
  1265.             return TypeToNameInfo(objectInfo.objectType, objectInfo, Converter.ToCode(objectInfo.objectType), null);
  1266.         }
  1267.         private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo, NameInfo nameInfo)
  1268.         {
  1269.             return TypeToNameInfo(objectInfo.objectType, objectInfo, Converter.ToCode(objectInfo.objectType), nameInfo);
  1270.         }
  1271.         private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo, InternalPrimitiveTypeE code)
  1272.         {
  1273.             return TypeToNameInfo(objectInfo.objectType, objectInfo, code, null);
  1274.         }
  1275.         private void TypeToNameInfo(Type type, NameInfo nameInfo)
  1276.         {
  1277.             TypeToNameInfo(type, null, Converter.ToCode(type), nameInfo);
  1278.         }
  1279.         // Transforms an Array to the serialized string form.
  1280.         private NameInfo ArrayTypeToNameInfo(WriteObjectInfo objectInfo, out NameInfo arrayElemTypeNameInfo)
  1281.         {
  1282.             InternalST.Soap( this, "ArrayTypeToNameInfo Entry ",objectInfo.objectType);
  1283.             NameInfo arrayNameInfo = TypeToNameInfo(objectInfo);
  1284.             //arrayElemTypeNameInfo = TypeToNameInfo(objectInfo.objectType.GetElementType());
  1285.             arrayElemTypeNameInfo = TypeToNameInfo(objectInfo.arrayElemObjectInfo);
  1286.             // Need to substitute XDR type for URT type in array.
  1287.             // E.g. Int32[] becomes I4[]
  1288.             ArrayNameToDisplayName(objectInfo, arrayElemTypeNameInfo);
  1289.             arrayNameInfo.NInameSpaceEnum = arrayElemTypeNameInfo.NInameSpaceEnum;
  1290.             arrayElemTypeNameInfo.NIisArray = arrayElemTypeNameInfo.NItype.IsArray;
  1291.             InternalST.Soap( this, "ArrayTypeToNameInfo Exit array ",arrayNameInfo.NIname," element ",arrayElemTypeNameInfo.NIname);            
  1292.             return arrayNameInfo;
  1293.         }
  1294.         private NameInfo MemberToNameInfo(String name)
  1295.         {
  1296.             NameInfo memberNameInfo = GetNameInfo();
  1297.             memberNameInfo.NInameSpaceEnum = InternalNameSpaceE.MemberName;
  1298.             memberNameInfo.NIname = name;
  1299.             return memberNameInfo;
  1300.         }
  1301.         private void ArrayNameToDisplayName(WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo)
  1302.         {
  1303.             InternalST.Soap( this, "ArrayNameToDisplayName Entry ",arrayElemTypeNameInfo.NIname);           
  1304.             String arrayElemTypeName = arrayElemTypeNameInfo.NIname;
  1305.             //String arrayElemTypeName = objectInfo.GetTypeFullName();;    
  1306.             InternalST.Soap( this, "ArrayNameToDisplayName Entry ",arrayElemTypeNameInfo.NIname, " Type full name ", arrayElemTypeName);            
  1307.             int arrayIndex = arrayElemTypeName.IndexOf('[');
  1308.             if (arrayIndex > 0)
  1309.             {
  1310.                 String elemBaseTypeString = arrayElemTypeName.Substring(0, arrayIndex);
  1311.                 InternalPrimitiveTypeE code = Converter.ToCode(elemBaseTypeString);
  1312.                 String convertedType = null;
  1313.                 bool isConverted = false;
  1314.                 if (code != InternalPrimitiveTypeE.Invalid)
  1315.                 {
  1316.                     if (code == InternalPrimitiveTypeE.Char)
  1317.                     {
  1318.                         convertedType = elemBaseTypeString;
  1319.                         arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.UrtSystem;
  1320.                     }
  1321.                     else
  1322.                     {
  1323.                         isConverted = true;
  1324.                         convertedType = Converter.ToXmlDataType(code);
  1325.                         String typeName = null;                 
  1326.                         arrayElemTypeNameInfo.NInameSpaceEnum = Converter.GetNameSpaceEnum(code, null, objectInfo, out typeName); 
  1327.                     }
  1328.                 }
  1329.                 else
  1330.                 {
  1331.                     InternalST.Soap( this, "ArrayNameToDisplayName elemBaseTypeString ",elemBaseTypeString);                                
  1332.                     if ((elemBaseTypeString.Equals("String")) || (elemBaseTypeString.Equals("System.String")))
  1333.                     {
  1334.                         isConverted = true;
  1335.                         convertedType = "string";
  1336.                         arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrString;
  1337.                     }
  1338.                     else if (elemBaseTypeString.Equals("System.Object"))
  1339.                     {
  1340.                         isConverted = true;
  1341.                         convertedType = "anyType";
  1342.                         arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive;
  1343.                     }
  1344.                     else
  1345.                     {
  1346.                         convertedType = elemBaseTypeString;
  1347.                     }
  1348.                 }
  1349.                 if (isConverted)
  1350.                 {
  1351.                     arrayElemTypeNameInfo.NIname = convertedType+arrayElemTypeName.Substring(arrayIndex);
  1352.                 }
  1353.             }
  1354.             else if (arrayElemTypeName.Equals("System.Object"))
  1355.             {
  1356.                 arrayElemTypeNameInfo.NIname = "anyType";
  1357.                 arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive;
  1358.             }
  1359.             InternalST.Soap( this, "ArrayNameToDisplayName Exit ",arrayElemTypeNameInfo.NIname);                        
  1360.         }
  1361.         private Hashtable assemblyToIdTable = new Hashtable(20);
  1362.         private StringBuilder sburi = new StringBuilder(50);
  1363.         private long GetAssemblyId(WriteObjectInfo objectInfo)
  1364.         {
  1365.             //use objectInfo to get assembly string with new criteria
  1366.             InternalST.Soap( this, "GetAssemblyId Entry ",objectInfo.objectType," isSi ",objectInfo.isSi);
  1367.             long assemId = 0;
  1368.             bool isNew = false;
  1369.             String assemblyString = objectInfo.GetAssemblyString();
  1370.             String serializedAssemblyString = assemblyString;
  1371.             if (assemblyString.Length == 0)
  1372.             {
  1373.                 // Fake type could returns an empty string
  1374.                 assemId = 0;
  1375.             }
  1376.             else if (assemblyString.Equals(Converter.urtAssemblyString))
  1377.             {
  1378.                 // Urt type is an assemId of 0. No assemblyString needs
  1379.                 // to be sent but for soap, dotted names need to be placed in header
  1380.                 InternalST.Soap( this, "GetAssemblyId urt Assembly String ");
  1381.                 assemId = 0;
  1382.                 isNew = false;
  1383.                 serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, null, (int)assemId, isNew, objectInfo.IsAttributeNameSpace());
  1384.             }
  1385.             else
  1386.             {
  1387.                 // Assembly needs to be sent
  1388.                 // Need to prefix assembly string to separate the string names from the
  1389.                 // assemblyName string names. That is a string can have the same value
  1390.                 // as an assemblyNameString, but it is serialized differently
  1391.                 if (assemblyToIdTable.ContainsKey(assemblyString))
  1392.                 {
  1393.                     assemId = (long)assemblyToIdTable[assemblyString];
  1394.                     isNew = false;
  1395.                 }
  1396.                 else
  1397.                 {
  1398.                     assemId = m_idGenerator.GetId("___AssemblyString___"+assemblyString, out isNew);
  1399.                     assemblyToIdTable[assemblyString] = assemId;
  1400.                 }
  1401.                 if (assemblyString != null && !objectInfo.IsInteropNameSpace())
  1402.                 {
  1403.                     if (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple)
  1404.                     {
  1405.                         // Use only the simple assembly name (not version or strong name)
  1406.                         int index = assemblyString.IndexOf(',');
  1407.                         if (index > 0)
  1408.                             serializedAssemblyString = assemblyString.Substring(0, index);
  1409.                     }
  1410.                 }
  1411.                 serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, serializedAssemblyString, (int)assemId, isNew, objectInfo.IsInteropNameSpace());
  1412.             }
  1413.             InternalST.Soap( this, "GetAssemblyId Exit id ",assemId," isNew ",isNew," assemblyString ",serializedAssemblyString);
  1414.             return assemId;
  1415.         }
  1416.         private bool IsEmbeddedAttribute(Type type)
  1417.         {
  1418.             InternalST.Soap( this," IsEmbedded Entry ",type);
  1419.             bool isEmbedded = false;
  1420.             if (type.IsValueType)
  1421.                 isEmbedded = true;
  1422.             else
  1423.             {
  1424.                 SoapTypeAttribute attr = (SoapTypeAttribute)
  1425.                                          InternalRemotingServices.GetCachedSoapAttribute(type);
  1426.                 isEmbedded = attr.Embedded;             
  1427.             }
  1428.             InternalST.Soap( this," IsEmbedded Exit ",isEmbedded);          
  1429.             return isEmbedded;
  1430.         }
  1431.         private void WriteEnum(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data, bool isAttribute)
  1432.         {
  1433.             InternalST.Soap( this, "WriteEnum ", memberNameInfo.NIname," type ", typeNameInfo.NItype," data ",((Enum)data).ToString());
  1434.             // An enum is written out as a string
  1435.             if (isAttribute)
  1436.                 serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, ((Enum)data).ToString());
  1437.             else
  1438.                 serWriter.WriteMember(memberNameInfo, typeNameInfo, ((Enum)data).ToString());
  1439.         }           
  1440.         private Type GetType(Object obj)
  1441.         {
  1442.             Type type = null;
  1443.             if (RemotingServices.IsTransparentProxy(obj))
  1444.                 type = Converter.typeofMarshalByRefObject;
  1445.             else
  1446.                 type = obj.GetType();
  1447.             return type;
  1448.         }
  1449.         private SerStack niPool = new SerStack("NameInfo Pool");
  1450.         private NameInfo GetNameInfo()
  1451.         {
  1452.             NameInfo nameInfo = null;
  1453.             if (!niPool.IsEmpty())
  1454.             {
  1455.                 nameInfo = (NameInfo)niPool.Pop();
  1456.                 nameInfo.Init();
  1457.             }
  1458.             else
  1459.                 nameInfo = new NameInfo();
  1460.             return nameInfo;
  1461.         }
  1462.         private bool CheckTypeFormat(FormatterTypeStyle test, FormatterTypeStyle want)
  1463.         {
  1464.             return(test & want) == want;
  1465.         }
  1466.         private void PutNameInfo(NameInfo nameInfo)
  1467.         {
  1468.             niPool.Push(nameInfo);
  1469.         }
  1470.     }
  1471. }