- // ==++==
- //
- //
- // Copyright (c) 2002 Microsoft Corporation. All rights reserved.
- //
- // The use and distribution terms for this software are contained in the file
- // named license.txt, which can be found in the root of this distribution.
- // By using this software in any fashion, you are agreeing to be bound by the
- // terms of this license.
- //
- // You must not remove this notice, or any other, from this software.
- //
- //
- // ==--==
- //============================================================
- //
- // Class: ObjectWriter
- // Purpose: Serializes an object graph into XML in SOAP format
- //
- // Date: June 10, 1999
- //
- //============================================================
- namespace System.Runtime.Serialization.Formatters.Soap
- {
- using System;
- using System.IO;
- using System.Reflection;
- using System.Collections;
- using System.Text;
- using System.Runtime.Remoting;
- using System.Runtime.Remoting.Messaging;
- using System.Runtime.Remoting.Metadata;
- using System.Runtime.Remoting.Metadata.W3cXsd2001;
- using System.Runtime.Serialization;
- using System.Security.Permissions;
- using System.Diagnostics;
- internal sealed class ObjectWriter
- {
- private Queue m_objectQueue;
- private ObjectIDGenerator m_idGenerator;
- private Stream m_stream;
- private ISurrogateSelector m_surrogates;
- private StreamingContext m_context;
- private SoapWriter serWriter;
- //Keeps track of types written
- // Null members are only written the first time for XML.
- private System.Collections.Hashtable m_serializedTypeTable;
- private long topId;
- private String topName = null;
- private Header[] headers;
- private InternalFE formatterEnums;
- private SerObjectInfoInit serObjectInfoInit = null;
- private IFormatterConverter m_formatterConverter;
- // Default header name space
- private String headerNamespace = "http://schemas.microsoft.com/clr/soap";
- private bool bRemoting = false;
- internal static SecurityPermission serializationPermission = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
- PrimitiveArray primitiveArray = null;
- // XMLObjectWriter Constructor
- internal ObjectWriter(Stream stream, ISurrogateSelector selector, StreamingContext context,InternalFE formatterEnums)
- {
- if (stream==null)
- {
- throw new ArgumentNullException("stream", SoapUtil.GetResourceString("ArgumentNull_Stream"));
- }
- m_stream=stream;
- m_surrogates = selector;
- m_context = context;
- this.formatterEnums = formatterEnums;
- InternalST.InfoSoap(
- formatterEnums.FEtypeFormat +" "+
- ((Enum)formatterEnums.FEserializerTypeEnum));
- m_formatterConverter = new FormatterConverter();
- }
- // Commences the process of serializing the entire graph.
- // initialize the graph walker.
- internal void Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
- {
- InternalST.Soap( this, "Serialize Entry 2 ",graph,((headers == null)?" no headers ": "headers"));
- serializationPermission.Demand();
- if (graph == null)
- throw new ArgumentNullException("graph",SoapUtil.GetResourceString("ArgumentNull_Graph"));
- if (serWriter == null)
- throw new ArgumentNullException("serWriter",String.Format(SoapUtil.GetResourceString("ArgumentNull_WithParamName"), "serWriter"));
- serObjectInfoInit = new SerObjectInfoInit();
- this.serWriter = serWriter;
- this.headers = inHeaders;
- if (graph is IMethodMessage)
- {
- bRemoting = true;
- MethodBase methodBase = ((IMethodMessage)graph).MethodBase;
- if (methodBase != null)
- serWriter.WriteXsdVersion(ProcessTypeAttributes(methodBase.ReflectedType));
- else
- serWriter.WriteXsdVersion(XsdVersion.V2001);
- }
- else
- serWriter.WriteXsdVersion(XsdVersion.V2001);
- m_idGenerator = new ObjectIDGenerator();
- m_objectQueue = new Queue();
- if (graph is ISoapMessage)
- {
- // Fake method call is to be written
- bRemoting = true;
- ISoapMessage ismc = (ISoapMessage)graph;
- graph = new InternalSoapMessage(ismc.MethodName, ismc.XmlNameSpace, ismc.ParamNames, ismc.ParamValues, ismc.ParamTypes);
- headers = ismc.Headers;
- }
- InternalST.Soap( this, "Serialize New SerializedTypeTable");
- m_serializedTypeTable = new Hashtable();
- serWriter.WriteBegin();
- long headerId = 0;
- Object obj;
- long objectId;
- bool isNew;
- topId = m_idGenerator.GetId(graph, out isNew);
- if (headers != null)
- headerId = m_idGenerator.GetId(headers, out isNew);
- else
- headerId = -1;
- WriteSerializedStreamHeader(topId, headerId);
- InternalST.Soap( this, "Serialize Schedule 0");
- // Write out SerializedStream header
- if (!((headers == null) || (headers.Length == 0)))
- {
- ProcessHeaders(headerId);
- }
- m_objectQueue.Enqueue(graph);
- while ((obj = GetNext(out objectId))!=null)
- {
- InternalST.Soap( this, "Serialize GetNext ",obj);
- WriteObjectInfo objectInfo = null;
- // GetNext will return either an object or a WriteObjectInfo.
- // A WriteObjectInfo is returned if this object was member of another object
- if (obj is WriteObjectInfo)
- {
- InternalST.Soap( this, "Serialize GetNext recognizes WriteObjectInfo");
- objectInfo = (WriteObjectInfo)obj;
- }
- else
- {
- objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
- objectInfo.assemId = GetAssemblyId(objectInfo);
- }
- objectInfo.objectId = objectId;
- NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
- typeNameInfo.NIisTopLevelObject = true;
- if (bRemoting && obj == graph)
- typeNameInfo.NIisRemoteRecord = true;
- Write(objectInfo, typeNameInfo, typeNameInfo);
- PutNameInfo(typeNameInfo);
- objectInfo.ObjectEnd();
- }
- serWriter.WriteSerializationHeaderEnd();
- serWriter.WriteEnd();
- m_idGenerator = new ObjectIDGenerator();
- InternalST.Soap( this, "*************Serialize New SerializedTypeTable 2");
- m_serializedTypeTable = new System.Collections.Hashtable();
- InternalST.Soap( this, "Serialize Exit ");
- }
- private XsdVersion ProcessTypeAttributes(Type type)
- {
- // Check to see if the xsd and xsi schema types should be 1999 instead of 2000. This is a temporary fix for an interop problem
- SoapTypeAttribute att = InternalRemotingServices.GetCachedSoapAttribute(type) as SoapTypeAttribute;
- XsdVersion xsdVersion = XsdVersion.V2001;
- if (att != null)
- {
- SoapOption soapOption = att.SoapOptions;
- if ((soapOption &= SoapOption.Option1) == SoapOption.Option1)
- xsdVersion = XsdVersion.V1999;
- else if ((soapOption &= SoapOption.Option1) == SoapOption.Option2)
- xsdVersion = XsdVersion.V2000;
- }
- return xsdVersion;
- }
- private void ProcessHeaders(long headerId)
- {
- long objectId;
- Object obj;
- // XML Serializer
- serWriter.WriteHeader((int)headerId, headers.Length);
- for (int i=0; i<headers.Length; i++)
- {
- Type headerValueType = null;
- if (headers[i].Value != null)
- headerValueType = GetType(headers[i].Value);
- if ((headerValueType != null) && (headerValueType == Converter.typeofString))
- {
- NameInfo nameInfo = GetNameInfo();
- nameInfo.NInameSpaceEnum = InternalNameSpaceE.UserNameSpace;
- nameInfo.NIname = headers[i].Name;
- nameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
- nameInfo.NIobjectId = -1;
- // Header will need to add a name space field which will if it doesn't the following
- // is the default name space
- HeaderNamespace(headers[i], nameInfo);
- serWriter.WriteHeaderString(nameInfo, headers[i].Value.ToString());
- PutNameInfo(nameInfo);
- }
- else if (headers[i].Name.Equals("__MethodSignature"))
- {
- InternalST.Soap( this, "Serialize Write Header __MethodSignature ");
- // Process message signature
- if (!(headers[i].Value is Type[]))
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_MethodSignature"), headerValueType));
- // Replace type array with an array of TypeToNameInfo's
- Type[] types = (Type[])headers[i].Value;
- NameInfo[] typeToNameInfos = new NameInfo[types.Length];
- WriteObjectInfo[] objectInfos = new WriteObjectInfo[types.Length];
- for (int j=0; j< types.Length; j++)
- {
- objectInfos[j] = WriteObjectInfo.Serialize(types[j], m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
- objectInfos[j].objectId = -1;
- objectInfos[j].assemId = GetAssemblyId(objectInfos[j]);
- typeToNameInfos[j] = TypeToNameInfo(objectInfos[j]);
- }
- // Create MemberNameInfo
- NameInfo memberNameInfo = MemberToNameInfo(headers[i].Name);
- memberNameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
- memberNameInfo.NItransmitTypeOnMember = true;
- memberNameInfo.NIisNestedObject = true;
- memberNameInfo.NIisHeader = true;
- HeaderNamespace(headers[i], memberNameInfo);
- serWriter.WriteHeaderMethodSignature(memberNameInfo, typeToNameInfos);
- for (int j=0; j<types.Length; j++)
- {
- PutNameInfo(typeToNameInfos[j]);
- objectInfos[j].ObjectEnd();
- }
- PutNameInfo(memberNameInfo);
- }
- else
- {
- InternalPrimitiveTypeE code = InternalPrimitiveTypeE.Invalid;
- long valueId;
- if (headerValueType != null)
- code = Converter.ToCode(headerValueType);
- if ((headerValueType != null) && (code == InternalPrimitiveTypeE.Invalid))
- {
- // Object reference
- InternalST.Soap( this, "Serialize Schedule 2");
- valueId = Schedule(headers[i].Value, headerValueType);
- if (valueId == -1)
- {
- WriteObjectInfo objectInfo = WriteObjectInfo.Serialize(headers[i].Value, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
- objectInfo.objectId = -1;
- objectInfo.assemId = GetAssemblyId(objectInfo);
- NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
- NameInfo memberNameInfo = MemberToNameInfo(headers[i].Name);
- memberNameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
- memberNameInfo.NItransmitTypeOnMember = true;
- memberNameInfo.NIisNestedObject = true;
- memberNameInfo.NIisHeader = true;
- HeaderNamespace(headers[i], memberNameInfo);
- Write(objectInfo, memberNameInfo, typeNameInfo);
- PutNameInfo(typeNameInfo);
- PutNameInfo(memberNameInfo);
- objectInfo.ObjectEnd();
- }
- InternalST.Soap( this, "Serialize Write Header Object Reference ");
- NameInfo refNameInfo = MemberToNameInfo(headers[i].Name);
- refNameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
- refNameInfo.NIobjectId = valueId;
- refNameInfo.NItransmitTypeOnMember = true;
- refNameInfo.NIisNestedObject = true;
- HeaderNamespace(headers[i], refNameInfo);
- serWriter.WriteHeaderObjectRef(refNameInfo);
- PutNameInfo(refNameInfo);
- }
- else
- {
- // Primitive type or null
- InternalST.Soap( this, "Serialize Write Header primitive type ");
- NameInfo nameInfo = GetNameInfo();
- nameInfo.NInameSpaceEnum = InternalNameSpaceE.UserNameSpace;
- nameInfo.NIname = headers[i].Name;
- nameInfo.NIisMustUnderstand = headers[i].MustUnderstand;
- nameInfo.NIprimitiveTypeEnum = code;
- // Header will need to add a name space field which will if it doesn't the following
- // is the default name space
- HeaderNamespace(headers[i], nameInfo);
- NameInfo typeNameInfo = null;
- if (headerValueType != null)
- {
- typeNameInfo = TypeToNameInfo(headerValueType);
- typeNameInfo.NItransmitTypeOnMember = true;
- }
- serWriter.WriteHeaderEntry(nameInfo, typeNameInfo, headers[i].Value);
- PutNameInfo(nameInfo);
- if (headerValueType != null)
- PutNameInfo(typeNameInfo);
- }
- }
- }
- serWriter.WriteHeaderArrayEnd();
- // Serialize headers ahead of top graph
- while ((obj = GetNext(out objectId))!=null)
- {
- WriteObjectInfo objectInfo = null;
- // GetNext will return either an object or a WriteObjectInfo.
- // A WriteObjectInfo is returned if this object was member of another object
- if (obj is WriteObjectInfo)
- {
- InternalST.Soap( this, "Serialize GetNext recognizes WriteObjectInfo");
- objectInfo = (WriteObjectInfo)obj;
- }
- else
- {
- objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
- objectInfo.assemId = GetAssemblyId(objectInfo);
- }
- objectInfo.objectId = objectId;
- NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
- Write(objectInfo, typeNameInfo, typeNameInfo);
- PutNameInfo(typeNameInfo);
- objectInfo.ObjectEnd();
- }
- serWriter.WriteHeaderSectionEnd();
- }
- private void HeaderNamespace(Header header, NameInfo nameInfo)
- {
- if (header.HeaderNamespace == null)
- nameInfo.NInamespace = headerNamespace;
- else
- nameInfo.NInamespace = header.HeaderNamespace;
- bool isNew = false;
- nameInfo.NIheaderPrefix = "h"+InternalGetId(nameInfo.NInamespace, Converter.typeofString, out isNew);
- }
- // Writes a given object to the stream.
- private void Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
- {
- InternalST.Soap( this, "Write 1 Entry objectInfo ",objectInfo,", memberNameInfo ",memberNameInfo,", typeNameInfo ",typeNameInfo);
- memberNameInfo.Dump("Write memberNameInfo");
- typeNameInfo.Dump("Write typeNameInfo");
- Object obj = objectInfo.obj;
- if (obj==null)
- throw new ArgumentNullException("objectInfo.obj", String.Format(SoapUtil.GetResourceString("Serialization_ArgumentNull_Obj"), objectInfo.objectType));
- Type objType = objectInfo.objectType;
- long objectId = objectInfo.objectId;
- InternalST.Soap( this, "Write 1 ",obj," ObjectId ",objectId);
- if (objType == Converter.typeofString)
- {
- // Top level String
- memberNameInfo.NIobjectId = objectId;
- serWriter.WriteObjectString(memberNameInfo, obj.ToString());
- }
- else if (objType == Converter.typeofTimeSpan)
- {
- // Top level TimeSpan
- serWriter.WriteTopPrimitive(memberNameInfo, obj);
- }
- else
- {
- if (objType.IsArray)
- {
- WriteArray(objectInfo, null, null);
- }
- else
- {
- String[] memberNames;
- Type[] memberTypes;
- Object[] memberData;
- SoapAttributeInfo[] memberAttributeInfo;
- objectInfo.GetMemberInfo(out memberNames, out memberTypes, out memberData, out memberAttributeInfo);
- // Only Binary needs to transmit types for ISerializable because the binary formatter transmits the types in URT format.
- // Soap transmits all types as strings, so it is up to the ISerializable object to convert the string back to its URT type
- if (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))
- {
- InternalST.Soap( this, "Write 1 TransmitOnObject ");
- memberNameInfo.NItransmitTypeOnObject = true;
- memberNameInfo.NIisParentTypeOnObject = true;
- typeNameInfo.NItransmitTypeOnObject = true;
- typeNameInfo.NIisParentTypeOnObject = true;
- }
- WriteObjectInfo[] memberObjectInfos = new WriteObjectInfo[memberNames.Length];
- // Get assembly information
- // Binary Serializer, assembly names need to be
- // written before objects are referenced.
- // GetAssemId here will write out the
- // assemblyStrings at the right Binary
- // Serialization object boundary.
- for (int i=0; i<memberTypes.Length; i++)
- {
- Type type = null;
- if (memberData[i] != null)
- type = GetType(memberData[i]);
- else
- type = typeof(Object);
- InternalPrimitiveTypeE code = Converter.ToCode(type);
- 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()))))
- {
- if (memberData[i] != null)
- {
- memberObjectInfos[i] =
- WriteObjectInfo.Serialize
- (
- memberData[i],
- m_surrogates,
- m_context,
- serObjectInfoInit,
- m_formatterConverter,
- (memberAttributeInfo == null)? null : memberAttributeInfo[i]
- );
- memberObjectInfos[i].assemId = GetAssemblyId(memberObjectInfos[i]);
- }
- else
- {
- memberObjectInfos[i] =
- WriteObjectInfo.Serialize
- (
- memberTypes[i],
- m_surrogates,
- m_context,
- serObjectInfoInit,
- m_formatterConverter,
- ((memberAttributeInfo == null) ? null : memberAttributeInfo[i])
- );
- memberObjectInfos[i].assemId = GetAssemblyId(memberObjectInfos[i]);
- }
- }
- }
- Write(objectInfo, memberNameInfo, typeNameInfo, memberNames, memberTypes, memberData, memberObjectInfos);
- }
- InternalST.Soap( this, "Write 1 ",obj," type ",GetType(obj));
- // After first time null members do not have to be written
- if (!(m_serializedTypeTable.ContainsKey(objType)))
- {
- InternalST.Soap( this, "Serialize SerializedTypeTable Add ",objType," obj ",obj);
- m_serializedTypeTable.Add(objType, objType);
- }
- }
- InternalST.Soap( this, "Write 1 Exit ",obj);
- }
- // Writes a given object to the stream.
- private void Write(WriteObjectInfo objectInfo,
- NameInfo memberNameInfo,
- NameInfo typeNameInfo,
- String[] memberNames,
- Type[] memberTypes,
- Object[] memberData,
- WriteObjectInfo[] memberObjectInfos)
- {
- InternalST.Soap( this, "Write 2 Entry obj ",objectInfo.obj,". objectId ",objectInfo.objectId,", objType ",typeNameInfo.NIname,", memberName ",memberNameInfo.NIname,", memberType ",typeNameInfo.NIname,", isMustUnderstand ",memberNameInfo.NIisMustUnderstand);
- int numItems = memberNames.Length;
- NameInfo topNameInfo = null;
- // Process members which will be written out as Soap attributes first
- if (objectInfo.cache.memberAttributeInfos != null)
- {
- InternalST.Soap( this, "Write Attribute Members");
- for (int i=0; i<objectInfo.cache.memberAttributeInfos.Length; i++)
- {
- InternalST.Soap( this, "Write Attribute Members name ", memberNames[i]);
- if ((objectInfo.cache.memberAttributeInfos[i] != null) &
- (objectInfo.cache.memberAttributeInfos[i].IsXmlAttribute()))
- WriteMemberSetup(objectInfo, memberNameInfo, typeNameInfo, memberNames[i], memberTypes[i], memberData[i], memberObjectInfos[i], true);
- }
- }
- if (memberNameInfo != null)
- {
- InternalST.Soap( this, "Write 2 ObjectBegin, memberName ",memberNameInfo.NIname);
- memberNameInfo.NIobjectId = objectInfo.objectId;
- serWriter.WriteObject(memberNameInfo, typeNameInfo, numItems, memberNames, memberTypes, memberObjectInfos);
- }
- else if ((objectInfo.objectId == topId) && (topName != null))
- {
- InternalST.Soap( this, "Write 2 ObjectBegin, topId method name ",topName);
- topNameInfo = MemberToNameInfo(topName);
- topNameInfo.NIobjectId = objectInfo.objectId;
- serWriter.WriteObject(topNameInfo, typeNameInfo, numItems, memberNames, memberTypes, memberObjectInfos);
- }
- else
- {
- if (objectInfo.objectType != Converter.typeofString)
- {
- InternalST.Soap( this, "Write 2 ObjectBegin, default ", typeNameInfo.NIname);
- typeNameInfo.NIobjectId = objectInfo.objectId;
- serWriter.WriteObject(typeNameInfo, null, numItems, memberNames, memberTypes, memberObjectInfos);
- }
- }
- if (memberNameInfo.NIisParentTypeOnObject)
- {
- memberNameInfo.NItransmitTypeOnObject = true;
- memberNameInfo.NIisParentTypeOnObject = false;
- }
- else
- memberNameInfo.NItransmitTypeOnObject = false;
- // Write members
- for (int i=0; i<numItems; i++)
- {
- if ((objectInfo.cache.memberAttributeInfos == null) ||
- (objectInfo.cache.memberAttributeInfos[i] == null) ||
- (!(objectInfo.cache.memberAttributeInfos[i].IsXmlAttribute())))
- WriteMemberSetup(objectInfo, memberNameInfo, typeNameInfo, memberNames[i], memberTypes[i], memberData[i], memberObjectInfos[i], false);
- }
- if (memberNameInfo != null)
- {
- memberNameInfo.NIobjectId = objectInfo.objectId;
- serWriter.WriteObjectEnd(memberNameInfo, typeNameInfo);
- }
- else if ((objectInfo.objectId == topId) && (topName != null))
- {
- serWriter.WriteObjectEnd(topNameInfo, typeNameInfo);
- PutNameInfo(topNameInfo);
- }
- else
- {
- if (objectInfo.objectType != Converter.typeofString)
- {
- String objectName = objectInfo.GetTypeFullName();
- serWriter.WriteObjectEnd(typeNameInfo, typeNameInfo);
- }
- }
- InternalST.Soap( this, "Write 2 Exit");
- }
- private void WriteMemberSetup(WriteObjectInfo objectInfo,
- NameInfo memberNameInfo,
- NameInfo typeNameInfo,
- String memberName,
- Type memberType,
- Object memberData,
- WriteObjectInfo memberObjectInfo,
- bool isAttribute
- )
- {
- NameInfo newMemberNameInfo = MemberToNameInfo(memberName);
- // newMemberNameInfo contains the member type
- if (memberObjectInfo != null)
- newMemberNameInfo.NIassemId = memberObjectInfo.assemId;
- newMemberNameInfo.NItype = memberType;
- // newTypeNameInfo contains the data type
- NameInfo newTypeNameInfo = null;
- if (memberObjectInfo == null)
- {
- newTypeNameInfo = TypeToNameInfo(memberType);
- }
- else
- {
- newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
- }
- newMemberNameInfo.NIisRemoteRecord = typeNameInfo.NIisRemoteRecord;
- newMemberNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject;
- newMemberNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;
- WriteMembers(newMemberNameInfo, newTypeNameInfo, memberData, objectInfo, typeNameInfo, memberObjectInfo, isAttribute);
- PutNameInfo(newMemberNameInfo);
- PutNameInfo(newTypeNameInfo);
- }
- // Writes the members of an object
- private void WriteMembers(NameInfo memberNameInfo,
- NameInfo memberTypeNameInfo,
- Object memberData,
- WriteObjectInfo objectInfo,
- NameInfo typeNameInfo,
- WriteObjectInfo memberObjectInfo,
- bool isAttribute)
- {
- InternalST.Soap( this, "WriteMembers Entry memberType: ",memberTypeNameInfo.NIname," memberName: ",memberNameInfo.NIname," data: ",memberData," objectId: ",objectInfo.objectId, " Container object ",objectInfo.obj, " isAttribute ", isAttribute);
- Type memberType = memberNameInfo.NItype;
- // Types are transmitted for a member as follows:
- // The member is of type object
- // The member object of type is ISerializable and
- // Soap - the member is a non-primitive value type, or it is a primitive value type which needs types (TimeSpan, DateTime)
- // TimeSpan and DateTime are transmitted as UInt64 to keep their precision.
- // Binary - Types always transmitted.
- if ((memberType == Converter.typeofObject) ||
- (memberType.IsValueType && objectInfo.isSi &
- Converter.IsSiTransmitType(memberTypeNameInfo.NIprimitiveTypeEnum)))
- {
- memberTypeNameInfo.NItransmitTypeOnMember = true;
- memberNameInfo.NItransmitTypeOnMember = true;
- }
- if (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))
- {
- memberTypeNameInfo.NItransmitTypeOnObject = true;
- memberNameInfo.NItransmitTypeOnObject = true;
- memberNameInfo.NIisParentTypeOnObject = true;
- }
- if (CheckForNull(objectInfo, memberNameInfo, memberTypeNameInfo, memberData))
- {
- return;
- }
- Object outObj = memberData;
- Type outType = null;
- // If member type does not equal data type, transmit type on object.
- if (memberTypeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Invalid)
- {
- if (RemotingServices.IsTransparentProxy(outObj))
- outType = Converter.typeofMarshalByRefObject;
- else
- {
- outType = GetType(outObj);
- if (memberType != outType)
- {
- memberTypeNameInfo.NItransmitTypeOnMember = true;
- memberNameInfo.NItransmitTypeOnMember = true;
- }
- }
- }
- if (memberType == Converter.typeofObject)
- {
- memberType = GetType(memberData);
- if (memberObjectInfo == null)
- TypeToNameInfo(memberType, memberTypeNameInfo);
- else
- TypeToNameInfo(memberObjectInfo, memberTypeNameInfo);
- InternalST.Soap( this, "WriteMembers memberType Object, actual memberType ",memberType);
- }
- if (memberObjectInfo != null && memberObjectInfo.isArray)
- {
- // Array
- InternalST.Soap( this, "WriteMembers IsArray");
- long arrayId = 0;
- if (!(objectInfo.IsEmbeddedAttribute(memberNameInfo.NIname)|| IsEmbeddedAttribute(memberType)))
- {
- arrayId = Schedule(outObj, outType, memberObjectInfo);
- }
- if (arrayId > 0)
- {
- // Array as object
- InternalST.Soap( this, "WriteMembers Schedule 3");
- memberNameInfo.NIobjectId = arrayId;
- WriteObjectRef(memberNameInfo, arrayId);
- }
- else
- {
- // Nested Array
- serWriter.WriteMemberNested(memberNameInfo);
- memberObjectInfo.objectId = arrayId;
- memberNameInfo.NIobjectId = arrayId;
- memberNameInfo.NIisNestedObject = true;
- WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo);
- }
- InternalST.Soap( this, "WriteMembers Array Exit ");
- return;
- }
- if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData, isAttribute))
- {
- InternalST.Soap( this, "WriteMembers Object ",memberData);
- // In soap an enum is written out as a string
- if (memberTypeNameInfo.NItype.IsEnum)
- WriteEnum(memberNameInfo, memberTypeNameInfo, memberData, isAttribute);
- else
- {
- if (isAttribute)
- {
- // XmlAttribute must be a primitive type or string
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_NonPrimitive_XmlAttribute"), memberNameInfo.NIname));
- }
- // Value or NO_ID, need to explicitly check for IsValue because a top level
- // value class has an objectId of 1
- if ((memberType.IsValueType) || objectInfo.IsEmbeddedAttribute(memberNameInfo.NIname) || IsEmbeddedAttribute(outType))
- {
- InternalST.Soap( this, "WriteMembers Value Type or NO_ID parameter");
- serWriter.WriteMemberNested(memberNameInfo);
- memberObjectInfo.objectId = -1;
- NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
- newTypeNameInfo.NIobjectId = -1;
- memberNameInfo.NIisNestedObject = true;
- if (objectInfo.isSi)
- {
- memberTypeNameInfo.NItransmitTypeOnMember = true;
- memberNameInfo.NItransmitTypeOnMember = true;
- }
- Write( memberObjectInfo, memberNameInfo, newTypeNameInfo);
- PutNameInfo(newTypeNameInfo);
- memberObjectInfo.ObjectEnd();
- }
- else
- {
- InternalST.Soap( this, "WriteMembers Schedule 4");
- long memberObjectId = 0;
- memberObjectId = Schedule(outObj, outType, memberObjectInfo);
- if (memberObjectId < 0)
- {
- // Nested object
- InternalST.Soap( this, "WriteMembers Nesting");
- serWriter.WriteMemberNested(memberNameInfo);
- memberObjectInfo.objectId = -1;
- NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
- newTypeNameInfo.NIobjectId = -1;
- memberNameInfo.NIisNestedObject = true;
- Write(memberObjectInfo, memberNameInfo, newTypeNameInfo);
- PutNameInfo(newTypeNameInfo);
- memberObjectInfo.ObjectEnd();
- }
- else
- {
- // Object reference
- memberNameInfo.NIobjectId = memberObjectId;
- WriteObjectRef(memberNameInfo, memberObjectId);
- }
- }
- }
- }
- InternalST.Soap( this, "WriteMembers Exit ");
- }
- // Writes out an array
- private void WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo)
- {
- InternalST.Soap( this, "WriteArray Entry ",objectInfo.obj," ",objectInfo.objectId);
- bool isAllocatedMemberNameInfo = false;
- if (memberNameInfo == null)
- {
- memberNameInfo = TypeToNameInfo(objectInfo);
- memberNameInfo.NIisTopLevelObject = true;
- isAllocatedMemberNameInfo = true;
- }
- memberNameInfo.NIisArray = true;
- long objectId = objectInfo.objectId;
- memberNameInfo.NIobjectId = objectInfo.objectId;
- // Get array type
- System.Array array = (System.Array)objectInfo.obj;
- //Type arrayType = array.GetType();
- Type arrayType = objectInfo.objectType;
- // Get type of array element
- Type arrayElemType = arrayType.GetElementType();
- WriteObjectInfo arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, (memberObjectInfo == null) ? null : memberObjectInfo.typeAttributeInfo);
- arrayElemObjectInfo.assemId = GetAssemblyId(arrayElemObjectInfo);
- NameInfo arrayElemTypeNameInfo = null;
- NameInfo arrayNameInfo = ArrayTypeToNameInfo(objectInfo, out arrayElemTypeNameInfo);
- arrayNameInfo.NIobjectId = objectId;
- arrayNameInfo.NIisArray = true;
- arrayElemTypeNameInfo.NIobjectId = objectId;
- arrayElemTypeNameInfo.NItransmitTypeOnMember = memberNameInfo.NItransmitTypeOnMember;
- arrayElemTypeNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject;
- arrayElemTypeNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;
- // Get rank and length information
- int rank = array.Rank;
- int[] lengthA = new int[rank];
- int[] lowerBoundA = new int[rank];
- int[] upperBoundA = new int[rank];
- for (int i=0; i<rank; i++)
- {
- lengthA[i] = array.GetLength(i);
- lowerBoundA[i] = array.GetLowerBound(i);
- upperBoundA[i] = array.GetUpperBound(i);
- }
- InternalArrayTypeE arrayEnum;
- if (arrayElemType.IsArray)
- {
- if (rank == 1)
- arrayEnum = InternalArrayTypeE.Jagged;
- else
- arrayEnum = InternalArrayTypeE.Rectangular;
- }
- else if (rank == 1)
- arrayEnum = InternalArrayTypeE.Single;
- else
- arrayEnum = InternalArrayTypeE.Rectangular;
- InternalST.Soap( this, "WriteArray ArrayInfo type ",arrayType," rank ",rank);
- // Byte array
- if ((arrayElemType == Converter.typeofByte) && (rank == 1) && (lowerBoundA[0] == 0))
- {
- serWriter.WriteObjectByteArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0], (byte[])array);
- return;
- }
- if (arrayElemType == Converter.typeofObject)
- {
- memberNameInfo.NItransmitTypeOnMember = true;
- arrayElemTypeNameInfo.NItransmitTypeOnMember = true;
- }
- if (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))
- {
- memberNameInfo.NItransmitTypeOnObject = true;
- arrayElemTypeNameInfo.NItransmitTypeOnObject = true;
- }
- if (arrayEnum == InternalArrayTypeE.Single)
- {
- // Single Dimensional array
- InternalST.Soap( this, "WriteArray ARRAY_SINGLE ");
- arrayNameInfo.NIname = arrayElemTypeNameInfo.NIname+"["+lengthA[0]+"]";
- // BinaryFormatter array of primitive types is written out in the WriteSingleArray statement
- // as a byte buffer
- serWriter.WriteSingleArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0], array);
- if (Converter.IsWriteAsByteArray(arrayElemTypeNameInfo.NIprimitiveTypeEnum) && (lowerBoundA[0] == 0))
- {
- // If binaryformatter and array is of appopriate primitive type the array is
- // written out as a buffer of bytes. The array was transmitted in WriteSingleArray
- // If soap the index directly by array
- arrayElemTypeNameInfo.NIobjectId = 0;
- if (primitiveArray == null)
- primitiveArray = new PrimitiveArray(arrayElemTypeNameInfo.NIprimitiveTypeEnum, array);
- else
- primitiveArray.Init(arrayElemTypeNameInfo.NIprimitiveTypeEnum, array);
- int upperBound = upperBoundA[0]+1;
- for (int i = lowerBoundA[0]; i < upperBound; i++)
- {
- serWriter.WriteItemString(arrayElemTypeNameInfo, arrayElemTypeNameInfo, primitiveArray.GetValue(i));
- }
- }
- else
- {
- // Non-primitive type array
- Object[] objectA = null;
- if (!arrayElemType.IsValueType)
- objectA = (Object[])array;
- int upperBound = upperBoundA[0]+1;
- // Soap does not write out trailing nulls. lastValue is set to the last null value. This becomes the array's upperbound
- // Note: value classes can't be null
- if (objectA != null)
- {
- int lastValue = lowerBoundA[0]-1;
- for (int i = lowerBoundA[0]; i< upperBound; i++)
- {
- if (objectA[i] != null)
- lastValue = i;
- }
- upperBound = lastValue+1;
- }
- for (int i = lowerBoundA[0]; i < upperBound; i++)
- {
- if (objectA == null)
- WriteArrayMember(objectInfo, arrayElemTypeNameInfo, array.GetValue(i));
- else
- WriteArrayMember(objectInfo, arrayElemTypeNameInfo, objectA[i]);
- }
- }
- }
- else if (arrayEnum == InternalArrayTypeE.Jagged)
- {
- // Jagged Array
- InternalST.Soap( this, "WriteArray ARRAY_JAGGED");
- int index;
- String arrayElemTypeDimension = null;
- index = arrayNameInfo.NIname.IndexOf('[');
- if (index < 0)
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_Dimensions"),arrayElemTypeNameInfo.NIname));
- arrayElemTypeDimension = arrayNameInfo.NIname.Substring(index);
- InternalST.Soap( this, "WriteArray arrayNameInfo.NIname ",arrayNameInfo.NIname," arrayElemTypeNameInfo.NIname ",arrayElemTypeNameInfo.NIname," arrayElemTypeDimension ",arrayElemTypeDimension);
- arrayNameInfo.NIname = arrayElemTypeNameInfo.NIname+"["+lengthA[0]+"]";
- arrayNameInfo.NIobjectId = objectId;
- serWriter.WriteJaggedArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, lengthA[0], lowerBoundA[0]);
- Object[] objectA = (Object[])array;
- for (int i = lowerBoundA[0]; i < upperBoundA[0]+1; i++)
- {
- WriteArrayMember(objectInfo, arrayElemTypeNameInfo, objectA[i]);
- }
- }
- else
- {
- // Rectangle Array
- // Get the length for all the ranks
- InternalST.Soap( this, "WriteArray ARRAY_RECTANGLE");
- // Express array Type using XmlData Name
- int index;
- index = arrayNameInfo.NIname.IndexOf('[');
- // Create length dimension string in form [3,4,2]
- StringBuilder sb = new StringBuilder(10);
- sb.Append(arrayElemTypeNameInfo.NIname);
- sb.Append('[');
- for (int i=0; i<rank; i++)
- {
- sb.Append(lengthA[i]);
- if (i < rank-1)
- sb.Append(',');
- }
- sb.Append(']');
- arrayNameInfo.NIname = sb.ToString();
- arrayNameInfo.NIobjectId = objectId;
- serWriter.WriteRectangleArray(memberNameInfo, arrayNameInfo, arrayElemObjectInfo, arrayElemTypeNameInfo, rank, lengthA, lowerBoundA);
- IndexTraceMessage("WriteArray Rectangle ", lengthA);
- bool bzero = false;
- for (int i=0; i<rank; i++)
- {
- if (lengthA[i] == 0)
- {
- bzero = true;
- break;
- }
- }
- if (!bzero)
- WriteRectangle(objectInfo, rank, lengthA, array, arrayElemTypeNameInfo, lowerBoundA);
- }
- serWriter.WriteObjectEnd(memberNameInfo, arrayNameInfo);
- PutNameInfo(arrayElemTypeNameInfo);
- PutNameInfo(arrayNameInfo);
- if (isAllocatedMemberNameInfo)
- PutNameInfo(memberNameInfo);
- InternalST.Soap( this, "WriteArray Exit ");
- }
- // Writes out an array element
- private void WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, Object data)
- {
- InternalST.Soap( this, "WriteArrayMember ",data," baseArrayName ",arrayElemTypeNameInfo.NIname);
- arrayElemTypeNameInfo.NIisArrayItem = true;
- if (CheckForNull(objectInfo, arrayElemTypeNameInfo, arrayElemTypeNameInfo, data))
- return;
- NameInfo actualTypeInfo = null;
- Type dataType = null;
- bool isObjectOnMember = false;
- if (arrayElemTypeNameInfo.NItransmitTypeOnMember)
- isObjectOnMember = true;
- if (!isObjectOnMember && !arrayElemTypeNameInfo.NIisSealed)
- {
- dataType = GetType(data);
- if (arrayElemTypeNameInfo.NItype != dataType)
- isObjectOnMember = true;
- }
- if (isObjectOnMember)
- {
- // Object array, need type of member
- if (dataType == null)
- dataType = GetType(data);
- actualTypeInfo = TypeToNameInfo(dataType);
- actualTypeInfo.NItransmitTypeOnMember = true;
- actualTypeInfo.NIobjectId = arrayElemTypeNameInfo.NIobjectId;
- actualTypeInfo.NIassemId = arrayElemTypeNameInfo.NIassemId;
- actualTypeInfo.NIisArrayItem = true;
- actualTypeInfo.NIitemName = arrayElemTypeNameInfo.NIitemName;
- }
- else
- {
- actualTypeInfo = arrayElemTypeNameInfo;
- actualTypeInfo.NIisArrayItem = true;
- }
- if (!WriteKnownValueClass(arrayElemTypeNameInfo, actualTypeInfo, data, false))
- {
- Object obj = data;
- if (actualTypeInfo.NItype.IsEnum)
- {
- WriteObjectInfo newObjectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
- actualTypeInfo.NIassemId = GetAssemblyId(newObjectInfo);
- WriteEnum(arrayElemTypeNameInfo, actualTypeInfo, data, false);
- }
- else
- {
- long arrayId = Schedule(obj, actualTypeInfo.NItype);
- arrayElemTypeNameInfo.NIobjectId = arrayId;
- actualTypeInfo.NIobjectId = arrayId;
- if (arrayId < 1)
- {
- WriteObjectInfo newObjectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, null);
- newObjectInfo.objectId = arrayId;
- newObjectInfo.assemId = GetAssemblyId(newObjectInfo);
- InternalST.Soap( this, "WriteArrayMembers nested");
- if (dataType == null)
- dataType = GetType(data);
- if (data!=null && dataType.IsArray)
- {
- WriteArray(newObjectInfo, actualTypeInfo, null);
- }
- else
- {
- actualTypeInfo.NIisNestedObject = true;
- NameInfo typeNameInfo = TypeToNameInfo(newObjectInfo);
- typeNameInfo.NIobjectId = arrayId;
- newObjectInfo.objectId = arrayId;
- Write(newObjectInfo, actualTypeInfo, typeNameInfo);
- }
- newObjectInfo.ObjectEnd();
- }
- else
- serWriter.WriteItemObjectRef(arrayElemTypeNameInfo, (int)arrayId);
- }
- }
- if (arrayElemTypeNameInfo.NItransmitTypeOnMember)
- PutNameInfo(actualTypeInfo);
- }
- // Iterates over a Rectangle array, for each element of the array invokes WriteArrayMember
- private void WriteRectangle(WriteObjectInfo objectInfo, int rank, int[] maxA, System.Array array, NameInfo arrayElemNameTypeInfo, int[] lowerBoundA)
- {
- IndexTraceMessage("WriteRectangle Entry "+rank, maxA);
- int[] currentA = new int[rank];
- int[] indexMap = null;
- bool isLowerBound = false;
- if (lowerBoundA != null)
- {
- for (int i=0; i<rank; i++)
- {
- if (lowerBoundA[i] != 0)
- isLowerBound = true;
- }
- }
- if (isLowerBound)
- indexMap = new int[rank];
- bool isLoop = true;
- while (isLoop)
- {
- isLoop = false;
- if (isLowerBound)
- {
- for (int i=0; i<rank; i++)
- indexMap[i] = currentA[i]+lowerBoundA[i];
- WriteArrayMember(objectInfo, arrayElemNameTypeInfo, array.GetValue(indexMap));
- }
- else
- WriteArrayMember(objectInfo, arrayElemNameTypeInfo, array.GetValue(currentA));
- for (int irank = rank-1; irank>-1; irank--)
- {
- // Find the current or lower dimension which can be incremented.
- if (currentA[irank] < maxA[irank]-1)
- {
- // The current dimension is at maximum. Increase the next lower dimension by 1
- currentA[irank]++;
- if (irank < rank-1)
- {
- // The current dimension and higher dimensions are zeroed.
- for (int i = irank+1; i<rank; i++)
- currentA[i] = 0;
- }
- isLoop = true;
- break;
- }
- }
- }
- InternalST.Soap( this, "WriteRectangle Exit ");
- }
- // Traces a message with an array of int
- [Conditional("SER_LOGGING")]
- private void IndexTraceMessage(String message, int[] index)
- {
- StringBuilder sb = new StringBuilder(10);
- sb.Append("[");
- for (int i=0; i<index.Length; i++)
- {
- sb.Append(index[i]);
- if (i != index.Length -1)
- sb.Append(",");
- }
- sb.Append("]");
- InternalST.Soap( this, message+" ",sb.ToString());
- }
- // This gives back the next object to be serialized. Objects
- // are returned in a FIFO order based on how they were passed
- // to Schedule. The id of the object is put into the objID parameter
- // and the Object itself is returned from the function.
- private Object GetNext(out long objID)
- {
- InternalST.Soap( this, "GetNext Entry ");
- bool isNew;
- //The Queue is empty here. We'll throw if we try to dequeue the empty queue.
- if (m_objectQueue.Count==0)
- {
- objID=0;
- InternalST.Soap( this, "GetNext Exit null");
- return null;
- }
- Object obj = m_objectQueue.Dequeue();
- Object realObj = null;
- // A WriteObjectInfo is queued if this object was a member of another object
- InternalST.Soap( this, "GetNext ",obj);
- if (obj is WriteObjectInfo)
- {
- InternalST.Soap( this, "GetNext recognizes WriteObjectInfo");
- realObj = ((WriteObjectInfo)obj).obj;
- }
- else
- realObj = obj;
- objID = m_idGenerator.HasId(realObj, out isNew);
- if (isNew)
- {
- InternalST.Soap( this, "Object " , obj , " has never been assigned an id.");
- throw new SerializationException(String.Format(SoapUtil.GetResourceString("Serialization_ObjNoID"),obj));
- }
- InternalST.Soap( this, "GetNext Exit "+objID," ",obj);
- return obj;
- }
- Object previousObj = null;
- long previousId = 0;
- private long InternalGetId(Object obj, Type type, out bool isNew)
- {
- if (obj == previousObj)
- {
- isNew = false;
- return previousId;
- }
- if (type.IsValueType)
- {
- isNew = false;
- previousObj = obj;
- previousId = -1;
- return -1;
- }
- else
- {
- long objectId = m_idGenerator.GetId(obj, out isNew);
- previousObj = obj;
- previousId = objectId;
- return objectId;
- }
- }
- // Schedules an object for later serialization if it hasn't already been scheduled.
- // We get an ID for obj and put it on the queue for later serialization
- // if this is a new object id.
- private long Schedule(Object obj, Type type)
- {
- return Schedule(obj, type, null);
- }
- private long Schedule(Object obj, Type type, WriteObjectInfo objectInfo)
- {
- InternalST.Soap( this, "Schedule Entry ",((obj == null)?"null":obj));
- bool isNew;
- long id;
- if (obj==null)
- {
- InternalST.Soap(this, "Schedule Obj Null, id = 0 ");
- return 0;
- }
- id = InternalGetId(obj, type, out isNew);
- if (isNew)
- {
- if (objectInfo == null)
- m_objectQueue.Enqueue(obj);
- else
- m_objectQueue.Enqueue(objectInfo);
- }
- InternalST.Soap( this, "Schedule Exit, id: ",id," isNew: ",isNew);
- return id;
- }
- // Determines if a type is a primitive type, if it is it is written
- private bool WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data, bool isAttribute)
- {
- InternalST.Soap( this, "WriteKnownValueClass Entry ",typeNameInfo.NIname," ",data," ",memberNameInfo.NIname);
- memberNameInfo.Dump("WriteKnownValueClass memberNameInfo");
- typeNameInfo.Dump("WriteKnownValueClass typeNameInfo");
- if (typeNameInfo.NItype == Converter.typeofString)
- {
- if (isAttribute)
- serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, (String)data);
- else
- WriteString(memberNameInfo, typeNameInfo, data);
- }
- else
- {
- if (typeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Invalid)
- {
- InternalST.Soap( this, "WriteKnownValueClass Exit false");
- return false;
- }
- else
- {
- if (typeNameInfo.NIisArray) // null if an array
- serWriter.WriteItem(memberNameInfo, typeNameInfo, data);
- else
- {
- if (isAttribute)
- serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, data);
- else
- serWriter.WriteMember(memberNameInfo, typeNameInfo, data);
- }
- }
- }
- InternalST.Soap( this, "WriteKnownValueClass Exit true");
- return true;
- }
- // Writes an object reference to the stream.
- private void WriteObjectRef(NameInfo nameInfo, long objectId)
- {
- InternalST.Soap( this, "WriteObjectRef Entry ",nameInfo.NIname," ",objectId);
- serWriter.WriteMemberObjectRef(nameInfo, (int)objectId);
- InternalST.Soap( this, "WriteObjectRef Exit ");
- }
- // Writes a string into the XML stream
- private void WriteString(NameInfo memberNameInfo, NameInfo typeNameInfo, Object stringObject)
- {
- InternalST.Soap( this, "WriteString stringObject ",stringObject," memberName ",memberNameInfo.NIname);
- bool isFirstTime = true;
- long stringId = -1;
- if (!CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.XsdString))
- stringId= InternalGetId(stringObject, typeNameInfo.NItype, out isFirstTime);
- typeNameInfo.NIobjectId = stringId;
- InternalST.Soap( this, "WriteString stringId ",stringId," isFirstTime ",isFirstTime);
- if ((isFirstTime) || (stringId < 0))
- {
- if (typeNameInfo.NIisArray) // null if array
- serWriter.WriteItemString(memberNameInfo, typeNameInfo, (String)stringObject);
- else
- serWriter.WriteMemberString(memberNameInfo, typeNameInfo, (String)stringObject);
- }
- else
- {
- WriteObjectRef(memberNameInfo, stringId);
- }
- }
- // Writes a null member into the stream
- private bool CheckForNull(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, Object data)
- {
- InternalST.Soap( this, "CheckForNull Entry data ",Util.PString(data),", memberType ",Util.PString(typeNameInfo.NItype));
- bool isNull = false;
- if (data == null) // || Convert.IsDBNull(data)
- isNull = true;
- // Optimization, Null members are only written for Binary
- if (isNull)
- {
- InternalST.Soap( this, "CheckForNull Write");
- if (typeNameInfo.NItype.IsArray)
- {
- // Call can occur before typeNameInfo.NIisArray is set
- ArrayNameToDisplayName(objectInfo, typeNameInfo);
- }
- if (typeNameInfo.NIisArrayItem)
- serWriter.WriteNullItem(memberNameInfo, typeNameInfo);
- else
- serWriter.WriteNullMember(memberNameInfo, typeNameInfo);
- }
- InternalST.Soap( this, "CheckForNull Exit ",isNull);
- return isNull;
- }
- // Writes the SerializedStreamHeader
- private void WriteSerializedStreamHeader(long topId, long headerId)
- {
- serWriter.WriteSerializationHeader((int)topId, (int)headerId, 1, 0);
- }
- // Transforms a type to the serialized string form. URT Primitive types are converted to XMLData Types
- private NameInfo TypeToNameInfo(Type type, WriteObjectInfo objectInfo, InternalPrimitiveTypeE code, NameInfo nameInfo)
- {
- InternalST.Soap( this, "TypeToNameInfo Entry type ",type,", objectInfo ",objectInfo,", code ", ((Enum)code).ToString());
- if (nameInfo == null)
- nameInfo = GetNameInfo();
- else
- nameInfo.Init();
- nameInfo.NIisSealed = type.IsSealed;
- String typeName = null;
- nameInfo.NInameSpaceEnum = Converter.GetNameSpaceEnum(code, type, objectInfo, out typeName);
- nameInfo.NIprimitiveTypeEnum = code;
- nameInfo.NItype = type;
- nameInfo.NIname = typeName;
- if (objectInfo != null)
- {
- nameInfo.NIattributeInfo = objectInfo.typeAttributeInfo;
- nameInfo.NIassemId = objectInfo.assemId;
- }
- switch (nameInfo.NInameSpaceEnum)
- {
- case InternalNameSpaceE.XdrPrimitive:
- break;
- case InternalNameSpaceE.XdrString:
- nameInfo.NIname = "string";
- break;
- case InternalNameSpaceE.UrtSystem:
- break;
- case InternalNameSpaceE.UrtUser:
- //if (type.FullName.StartsWith("System."))
- if (type.Module.Assembly == Converter.urtAssembly)
- {
- // The type name could be an ISerializable
- // But the type returned (typeName) could be a fake
- // type
- }
- else
- {
- if (objectInfo == null)
- {
- InternalST.Soap( this, "TypeToNameInfo ObjectInfo is null 2 ",type);
- }
- }
- break;
- }
- InternalST.Soap( this, "TypeToNameInfo Exit ",type, " typeName "+nameInfo.NIname);
- return nameInfo;
- }
- private NameInfo TypeToNameInfo(Type type)
- {
- return TypeToNameInfo(type, null, Converter.ToCode(type), null);
- }
- private NameInfo TypeToNameInfo(Type type, InternalPrimitiveTypeE code)
- {
- return TypeToNameInfo(type, null, code, null);
- }
- private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo)
- {
- return TypeToNameInfo(objectInfo.objectType, objectInfo, Converter.ToCode(objectInfo.objectType), null);
- }
- private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo, NameInfo nameInfo)
- {
- return TypeToNameInfo(objectInfo.objectType, objectInfo, Converter.ToCode(objectInfo.objectType), nameInfo);
- }
- private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo, InternalPrimitiveTypeE code)
- {
- return TypeToNameInfo(objectInfo.objectType, objectInfo, code, null);
- }
- private void TypeToNameInfo(Type type, NameInfo nameInfo)
- {
- TypeToNameInfo(type, null, Converter.ToCode(type), nameInfo);
- }
- // Transforms an Array to the serialized string form.
- private NameInfo ArrayTypeToNameInfo(WriteObjectInfo objectInfo, out NameInfo arrayElemTypeNameInfo)
- {
- InternalST.Soap( this, "ArrayTypeToNameInfo Entry ",objectInfo.objectType);
- NameInfo arrayNameInfo = TypeToNameInfo(objectInfo);
- //arrayElemTypeNameInfo = TypeToNameInfo(objectInfo.objectType.GetElementType());
- arrayElemTypeNameInfo = TypeToNameInfo(objectInfo.arrayElemObjectInfo);
- // Need to substitute XDR type for URT type in array.
- // E.g. Int32[] becomes I4[]
- ArrayNameToDisplayName(objectInfo, arrayElemTypeNameInfo);
- arrayNameInfo.NInameSpaceEnum = arrayElemTypeNameInfo.NInameSpaceEnum;
- arrayElemTypeNameInfo.NIisArray = arrayElemTypeNameInfo.NItype.IsArray;
- InternalST.Soap( this, "ArrayTypeToNameInfo Exit array ",arrayNameInfo.NIname," element ",arrayElemTypeNameInfo.NIname);
- return arrayNameInfo;
- }
- private NameInfo MemberToNameInfo(String name)
- {
- NameInfo memberNameInfo = GetNameInfo();
- memberNameInfo.NInameSpaceEnum = InternalNameSpaceE.MemberName;
- memberNameInfo.NIname = name;
- return memberNameInfo;
- }
- private void ArrayNameToDisplayName(WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo)
- {
- InternalST.Soap( this, "ArrayNameToDisplayName Entry ",arrayElemTypeNameInfo.NIname);
- String arrayElemTypeName = arrayElemTypeNameInfo.NIname;
- //String arrayElemTypeName = objectInfo.GetTypeFullName();;
- InternalST.Soap( this, "ArrayNameToDisplayName Entry ",arrayElemTypeNameInfo.NIname, " Type full name ", arrayElemTypeName);
- int arrayIndex = arrayElemTypeName.IndexOf('[');
- if (arrayIndex > 0)
- {
- String elemBaseTypeString = arrayElemTypeName.Substring(0, arrayIndex);
- InternalPrimitiveTypeE code = Converter.ToCode(elemBaseTypeString);
- String convertedType = null;
- bool isConverted = false;
- if (code != InternalPrimitiveTypeE.Invalid)
- {
- if (code == InternalPrimitiveTypeE.Char)
- {
- convertedType = elemBaseTypeString;
- arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.UrtSystem;
- }
- else
- {
- isConverted = true;
- convertedType = Converter.ToXmlDataType(code);
- String typeName = null;
- arrayElemTypeNameInfo.NInameSpaceEnum = Converter.GetNameSpaceEnum(code, null, objectInfo, out typeName);
- }
- }
- else
- {
- InternalST.Soap( this, "ArrayNameToDisplayName elemBaseTypeString ",elemBaseTypeString);
- if ((elemBaseTypeString.Equals("String")) || (elemBaseTypeString.Equals("System.String")))
- {
- isConverted = true;
- convertedType = "string";
- arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrString;
- }
- else if (elemBaseTypeString.Equals("System.Object"))
- {
- isConverted = true;
- convertedType = "anyType";
- arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive;
- }
- else
- {
- convertedType = elemBaseTypeString;
- }
- }
- if (isConverted)
- {
- arrayElemTypeNameInfo.NIname = convertedType+arrayElemTypeName.Substring(arrayIndex);
- }
- }
- else if (arrayElemTypeName.Equals("System.Object"))
- {
- arrayElemTypeNameInfo.NIname = "anyType";
- arrayElemTypeNameInfo.NInameSpaceEnum = InternalNameSpaceE.XdrPrimitive;
- }
- InternalST.Soap( this, "ArrayNameToDisplayName Exit ",arrayElemTypeNameInfo.NIname);
- }
- private Hashtable assemblyToIdTable = new Hashtable(20);
- private StringBuilder sburi = new StringBuilder(50);
- private long GetAssemblyId(WriteObjectInfo objectInfo)
- {
- //use objectInfo to get assembly string with new criteria
- InternalST.Soap( this, "GetAssemblyId Entry ",objectInfo.objectType," isSi ",objectInfo.isSi);
- long assemId = 0;
- bool isNew = false;
- String assemblyString = objectInfo.GetAssemblyString();
- String serializedAssemblyString = assemblyString;
- if (assemblyString.Length == 0)
- {
- // Fake type could returns an empty string
- assemId = 0;
- }
- else if (assemblyString.Equals(Converter.urtAssemblyString))
- {
- // Urt type is an assemId of 0. No assemblyString needs
- // to be sent but for soap, dotted names need to be placed in header
- InternalST.Soap( this, "GetAssemblyId urt Assembly String ");
- assemId = 0;
- isNew = false;
- serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, null, (int)assemId, isNew, objectInfo.IsAttributeNameSpace());
- }
- else
- {
- // Assembly needs to be sent
- // Need to prefix assembly string to separate the string names from the
- // assemblyName string names. That is a string can have the same value
- // as an assemblyNameString, but it is serialized differently
- if (assemblyToIdTable.ContainsKey(assemblyString))
- {
- assemId = (long)assemblyToIdTable[assemblyString];
- isNew = false;
- }
- else
- {
- assemId = m_idGenerator.GetId("___AssemblyString___"+assemblyString, out isNew);
- assemblyToIdTable[assemblyString] = assemId;
- }
- if (assemblyString != null && !objectInfo.IsInteropNameSpace())
- {
- if (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple)
- {
- // Use only the simple assembly name (not version or strong name)
- int index = assemblyString.IndexOf(',');
- if (index > 0)
- serializedAssemblyString = assemblyString.Substring(0, index);
- }
- }
- serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, serializedAssemblyString, (int)assemId, isNew, objectInfo.IsInteropNameSpace());
- }
- InternalST.Soap( this, "GetAssemblyId Exit id ",assemId," isNew ",isNew," assemblyString ",serializedAssemblyString);
- return assemId;
- }
- private bool IsEmbeddedAttribute(Type type)
- {
- InternalST.Soap( this," IsEmbedded Entry ",type);
- bool isEmbedded = false;
- if (type.IsValueType)
- isEmbedded = true;
- else
- {
- SoapTypeAttribute attr = (SoapTypeAttribute)
- InternalRemotingServices.GetCachedSoapAttribute(type);
- isEmbedded = attr.Embedded;
- }
- InternalST.Soap( this," IsEmbedded Exit ",isEmbedded);
- return isEmbedded;
- }
- private void WriteEnum(NameInfo memberNameInfo, NameInfo typeNameInfo, Object data, bool isAttribute)
- {
- InternalST.Soap( this, "WriteEnum ", memberNameInfo.NIname," type ", typeNameInfo.NItype," data ",((Enum)data).ToString());
- // An enum is written out as a string
- if (isAttribute)
- serWriter.WriteAttributeValue(memberNameInfo, typeNameInfo, ((Enum)data).ToString());
- else
- serWriter.WriteMember(memberNameInfo, typeNameInfo, ((Enum)data).ToString());
- }
- private Type GetType(Object obj)
- {
- Type type = null;
- if (RemotingServices.IsTransparentProxy(obj))
- type = Converter.typeofMarshalByRefObject;
- else
- type = obj.GetType();
- return type;
- }
- private SerStack niPool = new SerStack("NameInfo Pool");
- private NameInfo GetNameInfo()
- {
- NameInfo nameInfo = null;
- if (!niPool.IsEmpty())
- {
- nameInfo = (NameInfo)niPool.Pop();
- nameInfo.Init();
- }
- else
- nameInfo = new NameInfo();
- return nameInfo;
- }
- private bool CheckTypeFormat(FormatterTypeStyle test, FormatterTypeStyle want)
- {
- return(test & want) == want;
- }
- private void PutNameInfo(NameInfo nameInfo)
- {
- niPool.Push(nameInfo);
- }
- }
- }