The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization.Formatters.Soap \ ObjectWriter

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

Developer Fusion