BinaryObjectWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / clr / src / BCL / System / Runtime / Serialization / Formatters / Binary / BinaryObjectWriter.cs / 1 / BinaryObjectWriter.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
 ** 
 ** Class: ObjectWriter 
 **
 ** 
 ** Purpose: Serializes an object graph into XML in SOAP format
 **
 **
 ===========================================================*/ 

namespace System.Runtime.Serialization.Formatters.Binary 
{ 
    using System;
    using System.IO; 
    using System.Reflection;
    using System.Reflection.Cache;
    using System.Collections;
    using System.Collections.Generic; 
    using System.Text;
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Messaging; 
    using System.Runtime.Serialization;
    using System.Security.Permissions; 
    using System.Security;
    using System.Diagnostics;
    using System.Globalization;
 
    internal sealed  class ObjectWriter
    { 
        private Queue m_objectQueue; 
        private ObjectIDGenerator m_idGenerator;
        private int m_currentId; 

        private ISurrogateSelector m_surrogates;
        private StreamingContext m_context;
        private __BinaryWriter serWriter; 
        private SerializationObjectManager m_objectManager;
 
        private long topId; 
        private String topName = null;
        private Header[] headers; 

        private InternalFE formatterEnums;

        private SerObjectInfoInit serObjectInfoInit = null; 

        private IFormatterConverter m_formatterConverter; 
 
        internal Object[] crossAppDomainArray = null;
        internal ArrayList internalCrossAppDomainArray = null; 

        // XMLObjectWriter Constructor
        internal ObjectWriter(ISurrogateSelector selector, StreamingContext context,InternalFE formatterEnums)
        { 
            m_currentId = 1;
            m_surrogates = selector; 
            m_context = context; 
            this.formatterEnums = formatterEnums;
            m_objectManager = new SerializationObjectManager(context); 
            SerTrace.InfoLog(
                            formatterEnums.FEtypeFormat +" "+
                            ((Enum)formatterEnums.FEserializerTypeEnum));
 

        } 
 
        // Commences the process of serializing the entire graph.
        // initialize the graph walker. 
        internal void Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, bool fCheck)
        {
            SerTrace.Log( this, "Serialize Entry 2 ",graph,((headers == null)?" no headers ": "headers "));
 
            if (fCheck)
            { 
                CodeAccessPermission.DemandInternal(PermissionType.SecuritySerialization); 
            }
 
            if (graph == null)
                throw new ArgumentNullException("graph",Environment.GetResourceString("ArgumentNull_Graph"));

            if (serWriter == null) 
                throw new ArgumentNullException("serWriter",String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentNull_WithParamName"), "serWriter"));
 
            this.serWriter = serWriter; 
            this.headers = inHeaders;
 
            SerTrace.Log( this, "Serialize New SerializedTypeTable");
            serWriter.WriteBegin();
            long headerId = 0;
            Object obj; 
            long objectId;
            bool isNew; 
            bool bMethodCall = false; 
            bool bMethodReturn = false;
 
            // Special case IMethodCallMessage and IMethodReturnMessage for performance
            IMethodCallMessage mess = graph as IMethodCallMessage;
            if (mess != null)
            { 
                bMethodCall = true;
                graph = WriteMethodCall(mess); 
            } 
            else
            { 
                IMethodReturnMessage mr = graph as IMethodReturnMessage;
                if (mr != null)
                {
                    bMethodReturn = true; 
                    graph = WriteMethodReturn(mr);
                } 
            } 

            if (graph == null) 
            {
                WriteSerializedStreamHeader(topId, headerId);

                if (bMethodCall) 
                    serWriter.WriteMethodCall();
                else if (bMethodReturn) 
                    serWriter.WriteMethodReturn(); 

                serWriter.WriteSerializationHeaderEnd(); 
                serWriter.WriteEnd();
                return;
            }
 
            // allocations if methodCall or methodResponse and no graph
            m_idGenerator = new ObjectIDGenerator(); 
            m_objectQueue = new Queue(); 
            m_formatterConverter = new FormatterConverter();
            serObjectInfoInit = new SerObjectInfoInit(); 

            topId = InternalGetId(graph, false, null, out isNew);

 
            if (headers != null)
                headerId = InternalGetId(headers, false, null, out isNew); 
            else 
                headerId = -1;
 
            WriteSerializedStreamHeader(topId, headerId);


            if (bMethodCall) 
                serWriter.WriteMethodCall();
            else if (bMethodReturn) 
                serWriter.WriteMethodReturn(); 

 
            SerTrace.Log( this, "Serialize Schedule 0");

            // Write out SerializedStream header
            if ((headers != null) && (headers.Length > 0)) 
                m_objectQueue.Enqueue(headers);
 
            if (graph != null) 
                m_objectQueue.Enqueue(graph);
 
            while ((obj = GetNext(out objectId))!=null)
            {
                SerTrace.Log( 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)
                { 
                    SerTrace.Log( this, "Serialize GetNext recognizes WriteObjectInfo");
                    objectInfo = (WriteObjectInfo)obj;
                }
                else 
                {
                    objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, this); 
                    objectInfo.assemId = GetAssemblyId(objectInfo); 
                }
 

                objectInfo.objectId = objectId;
                NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
                Write(objectInfo, typeNameInfo, typeNameInfo); 
                PutNameInfo(typeNameInfo);
                objectInfo.ObjectEnd(); 
            } 

            serWriter.WriteSerializationHeaderEnd(); 
            serWriter.WriteEnd();

            // Invoke OnSerialized Event
            m_objectManager.RaiseOnSerializedEvent(); 

            SerTrace.Log( this, "Serialize Exit "); 
        } 

        private Object[] WriteMethodCall(IMethodCallMessage mcm) 
        {
            // In header
            String uri = mcm.Uri;
            String methodName = mcm.MethodName; 
            String typeName = mcm.TypeName;
 
            // Optional 
            Object methodSignature = null;
            Object callContext = null; 
            Object[] properties = null;

            // instantiation args
            Type[] instArgs = null; 
            if (mcm.MethodBase.IsGenericMethod)
                instArgs = mcm.MethodBase.GetGenericArguments(); 
 
            // args
            Object[] args = mcm.Args; 

            IInternalMessage iim = mcm as IInternalMessage;

            // user properties (everything but special entries) 
            if ((iim == null) || iim.HasProperties())
                properties = StoreUserPropertiesForMethodMessage(mcm); 
 
            // handle method signature
            if (mcm.MethodSignature != null && RemotingServices.IsMethodOverloaded(mcm)) 
                methodSignature = mcm.MethodSignature;

            // handle call context
            LogicalCallContext lcc = mcm.LogicalCallContext; 
            if (lcc == null)
            { 
                callContext = null; 
            }
            else if (lcc.HasInfo) 
                callContext = lcc;
            else
            {
                // just smuggle the call id string 
                callContext = lcc.RemotingData.LogicalCallID;
            } 
 
            return serWriter.WriteCallArray(uri, methodName, typeName, instArgs, args, methodSignature, callContext, properties);
        } 


        private Object[] WriteMethodReturn(IMethodReturnMessage mrm)
        { 
            Object    returnValue = mrm.ReturnValue;
            Object[]  args = mrm.Args; 
            Exception exception = mrm.Exception; 
            Object callContext;
            Object[] properties = null; 

            ReturnMessage retMsg = mrm as ReturnMessage;

            // user properties (everything but special entries) 
            if ((retMsg == null) || retMsg.HasProperties())
                properties = StoreUserPropertiesForMethodMessage(mrm); 
 
            // handle call context
            LogicalCallContext lcc = mrm.LogicalCallContext; 
            if (lcc == null)
            {
                callContext = null;
            } 
            else if (lcc.HasInfo)
                callContext = lcc; 
            else 
            {
                // just smuggle the call id string 
                callContext = lcc.RemotingData.LogicalCallID;
            }

           return serWriter.WriteReturnArray(returnValue, args, exception, callContext, properties); 
        }
 
        // returns number of entries added to argsToSerialize 
        private static Object[] StoreUserPropertiesForMethodMessage(IMethodMessage msg)
        { 
            ArrayList argsToSerialize = null;
            IDictionary properties = msg.Properties;

            if (properties == null) 
                return null;
 
            MessageDictionary dict = properties as MessageDictionary; 
            if (dict != null)
            { 
                if (dict.HasUserData())
                {
                    int co = 0;
                    foreach (DictionaryEntry entry in dict.InternalDictionary) 
                    {
                        if (argsToSerialize == null) 
                            argsToSerialize = new ArrayList(); 
                        argsToSerialize.Add(entry);
                        co++; 
                    }

                    return argsToSerialize.ToArray();
                } 
                else
                { 
                    return null; 
                }
            } 
            else
            {
                // <
 

                int co = 0; 
                foreach (DictionaryEntry entry in properties) 
                {
                    if (argsToSerialize == null) 
                        argsToSerialize = new ArrayList();
                    argsToSerialize.Add(entry);
                    co++;
                } 

                if (argsToSerialize != null) 
                    return argsToSerialize.ToArray(); 
                else
                    return null; 
            }

        } // StoreUserPropertiesForMethodMessage
 
        internal SerializationObjectManager ObjectManager
        { 
            get { return m_objectManager; } 
        }
 
        // Writes a given object to the stream.
        private void Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
        {
#if _DEBUG 
            SerTrace.Log( this, "Write 1 Entry objectInfo ",objectInfo,", memberNameInfo ",memberNameInfo,", typeNameInfo ",typeNameInfo);
            memberNameInfo.Dump("Write memberNameInfo"); 
            typeNameInfo.Dump("Write typeNameInfo"); 
#endif
            Object obj = objectInfo.obj; 
            if (obj==null)
                throw new ArgumentNullException("objectInfo.obj", Environment.GetResourceString("ArgumentNull_Obj"));

            SerTrace.Log( this, "Write 1 objectInfo obj ",objectInfo.obj," objectId ", objectInfo.objectId, " objectType ", objectInfo.objectType); 
            Type objType = objectInfo.objectType;
            long objectId = objectInfo.objectId; 
 

            SerTrace.Log( this, "Write 1 ",obj," ObjectId ",objectId); 

            if (objType == Converter.typeofString)
            {
                // Top level String 
                memberNameInfo.NIobjectId = objectId;
                serWriter.WriteObjectString((int)objectId, obj.ToString()); 
            } 
            else
            { 

                if (objectInfo.isArray)
                {
                    WriteArray(objectInfo, memberNameInfo, null); 
                }
                else 
                { 
                    String[] memberNames;
                    Type[] memberTypes; 
                    Object[] memberData;

                    objectInfo.GetMemberInfo(out memberNames, out memberTypes, out memberData);
 
                    // 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 (objectInfo.isSi || CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways)) 
                    {
                        SerTrace.Log( 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 0)
                { 
                    // Array as object
                    SerTrace.Log( this, "WriteMembers Schedule 3"); 
                    memberNameInfo.NIobjectId = arrayId; 
                    WriteObjectRef(memberNameInfo, arrayId);
                } 
                else
                {
                    // Nested Array
                    serWriter.WriteMemberNested(memberNameInfo); 

                    memberObjectInfo.objectId = arrayId; 
                    memberNameInfo.NIobjectId = arrayId; 
                    WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo);
                    objectInfo.ObjectEnd(); 

                }
                SerTrace.Log( this, "WriteMembers Array Exit ");
                return; 
            }
 
            if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData)) 
            {
                SerTrace.Log( this, "WriteMembers Object ",memberData); 

#if false
                // Value or NO_ID, need to explicitly check for IsValue because a top level
                // value class has an objectId of 1 
                /*
                if (memberType.IsValueType) 
                { 
                    SerTrace.Log( this, "WriteMembers Value Type or NO_ID parameter");
 
                    bool isNew;
                    memberObjectInfo.objectId = InternalGetId(outObj, assignUniqueIdToValueType, memberType, out isNew) ;
                    NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
                    newTypeNameInfo.NIobjectId = memberObjectInfo.objectId; 
                    Write( memberObjectInfo, memberNameInfo, newTypeNameInfo);
                    PutNameInfo(newTypeNameInfo); 
                    memberObjectInfo.ObjectEnd(); 
                }
                else 
                */
#endif
                {
                    SerTrace.Log( this, "WriteMembers Schedule 4 ", outType, " memberInfo ",memberObjectInfo); 
                    if (outType == null)
                        outType = GetType(outObj); 
                    long memberObjectId = Schedule(outObj, assignUniqueIdToValueType, outType, memberObjectInfo); 
                    if (memberObjectId < 0)
                    { 
                        // Nested object
                        SerTrace.Log( this, "WriteMembers Nesting");

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

            SerTrace.Log( this, "WriteMembers Exit ");
        }
 
        // Writes out an array
        private void WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo) 
        { 
            SerTrace.Log( this, "WriteArray Entry ",objectInfo.obj," ",objectInfo.objectId);
 
            bool isAllocatedMemberNameInfo = false;
            if (memberNameInfo == null)
            {
                memberNameInfo = TypeToNameInfo(objectInfo); 
                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 = null;
            if (!arrayElemType.IsPrimitive)
            { 
                arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter);
                arrayElemObjectInfo.assemId = GetAssemblyId(arrayElemObjectInfo); 
            } 

 
            NameInfo arrayElemTypeNameInfo = null;
            if (arrayElemObjectInfo == null)
                arrayElemTypeNameInfo = TypeToNameInfo(arrayElemType);
            else 
                arrayElemTypeNameInfo = TypeToNameInfo(arrayElemObjectInfo);
            arrayElemTypeNameInfo.NIisArray = arrayElemTypeNameInfo.NItype.IsArray; 
 
            NameInfo arrayNameInfo = memberNameInfo;
            arrayNameInfo.NIobjectId = objectId; 
            arrayNameInfo.NIisArray = true;
            arrayElemTypeNameInfo.NIobjectId = objectId;
            arrayElemTypeNameInfo.NItransmitTypeOnMember = memberNameInfo.NItransmitTypeOnMember;
            arrayElemTypeNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject; 
            arrayElemTypeNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;
 
            // Get rank and length information 
            int rank = array.Rank;
            int[] lengthA = new int[rank]; 
            int[] lowerBoundA = new int[rank];
            int[] upperBoundA = new int[rank];
            for (int i=0; i-1; irank--) 
                {
                    // Find the current or lower dimension which can be incremented.
                    if (currentA[irank] < maxA[irank]-1)
                    { 
                        // The current dimension is at maximum. Increase the next lower dimension by 1
                        currentA[irank]++; 
                        if (irank < rank-1) 
                        {
                            // The current dimension and higher dimensions are zeroed. 
                            for (int i = irank+1; i 0)
            { 
                if (objectInfo == null)
                    m_objectQueue.Enqueue(obj);
                else
                    m_objectQueue.Enqueue(objectInfo); 

            } 
 
            SerTrace.Log( 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) 
        { 
#if _DEBUG
            SerTrace.Log( this, "WriteKnownValueClass Entry ",typeNameInfo.NIname," ",data," ",memberNameInfo.NIname); 
            memberNameInfo.Dump("WriteKnownValueClass memberNameInfo");
            typeNameInfo.Dump("WriteKnownValueClass typeNameInfo");
#endif
 
            if (typeNameInfo.NItype == Converter.typeofString)
            { 
                WriteString(memberNameInfo, typeNameInfo, data); 
            }
            else 
            {
                if (typeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Invalid)
                {
                    SerTrace.Log( this, "WriteKnownValueClass Exit false"); 
                    return false;
                } 
                else 
                {
                    if (typeNameInfo.NIisArray) // null if an array 
                        serWriter.WriteItem(memberNameInfo, typeNameInfo, data);
                    else
                    {
                        serWriter.WriteMember(memberNameInfo, typeNameInfo, data); 
                    }
                } 
            } 

            SerTrace.Log( this, "WriteKnownValueClass Exit true"); 
            return true;
        }

 
        // Writes an object reference to the stream.
        private void WriteObjectRef(NameInfo nameInfo, long objectId) 
        { 
            SerTrace.Log( this, "WriteObjectRef Entry ",nameInfo.NIname," ",objectId);
            serWriter.WriteMemberObjectRef(nameInfo, (int)objectId); 

            SerTrace.Log( this, "WriteObjectRef Exit ");
        }
 

 
        // Writes a string into the XML stream 
        private void WriteString(NameInfo memberNameInfo, NameInfo typeNameInfo, Object stringObject)
        { 
            SerTrace.Log( this, "WriteString stringObject ",stringObject," memberName ",memberNameInfo.NIname);
            bool isFirstTime = true;

            long stringId = -1; 

            if (!CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.XsdString)) 
                stringId= InternalGetId(stringObject, false, null, out isFirstTime); 

            typeNameInfo.NIobjectId = stringId; 
            SerTrace.Log( this, "WriteString stringId ",stringId," isFirstTime ",isFirstTime);

            if ((isFirstTime) || (stringId < 0))
                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)
        {
#if _DEBUG
            SerTrace.Log( this, "CheckForNull Entry data ",Util.PString(data),", memberType ",Util.PString(typeNameInfo.NItype)); 
#endif
            bool isNull = false; 
 
            if (data == null) // || Convert.IsDBNull(data)
                isNull = true; 

            // Optimization, Null members are only written for Binary
            if ((isNull) && (((formatterEnums.FEserializerTypeEnum == InternalSerializerTypeE.Binary)) ||
                             memberNameInfo.NIisArrayItem || 
                             memberNameInfo.NItransmitTypeOnObject ||
                             memberNameInfo.NItransmitTypeOnMember || 
                             objectInfo.isSi || 
                             (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))))
            { 
                SerTrace.Log( this, "CheckForNull Write");

                if (typeNameInfo.NIisArrayItem)
                { 
                    if (typeNameInfo.NIarrayEnum == InternalArrayTypeE.Single)
                        serWriter.WriteDelayedNullItem(); 
                    else 
                        serWriter.WriteNullItem(memberNameInfo, typeNameInfo);
                } 

                else
                    serWriter.WriteNullMember(memberNameInfo, typeNameInfo);
            } 
            SerTrace.Log( 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) 
        {
            SerTrace.Log( this, "TypeToNameInfo Entry type ",type,", objectInfo ",objectInfo,", code ", ((Enum)code).ToString());
            if (nameInfo == null)
                nameInfo = GetNameInfo(); 
            else
                nameInfo.Init(); 
 
            if (code == InternalPrimitiveTypeE.Invalid)
            { 
                if (objectInfo != null)
                {
                    nameInfo.NIname = objectInfo.GetTypeFullName();
                    nameInfo.NIassemId = objectInfo.assemId; 
                }
            } 
            nameInfo.NIprimitiveTypeEnum = code; 
            nameInfo.NItype = type;
 
            SerTrace.Log( this, "TypeToNameInfo Exit ",type, " typeName "+nameInfo.NIname);
            return nameInfo;
        }
 
        private NameInfo TypeToNameInfo(Type type)
        { 
            return TypeToNameInfo(type, null, ToCode(type), null); 
        }
 
        private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo)
        {
            return TypeToNameInfo(objectInfo.objectType, objectInfo, ToCode(objectInfo.objectType), null);
        } 

        private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo, NameInfo nameInfo) 
        { 
            return TypeToNameInfo(objectInfo.objectType, objectInfo, ToCode(objectInfo.objectType), nameInfo);
        } 

        private void TypeToNameInfo(Type type, NameInfo nameInfo)
        {
            TypeToNameInfo(type, null, ToCode(type), nameInfo); 
        }
 
        private NameInfo MemberToNameInfo(String name) 
        {
            NameInfo memberNameInfo = GetNameInfo(); 
            memberNameInfo.NIname = name;
            return memberNameInfo;
        }
 
        Type previousType = null;
        InternalPrimitiveTypeE previousCode = InternalPrimitiveTypeE.Invalid; 
        internal InternalPrimitiveTypeE ToCode(Type type) 
        {
            if (previousType == type) 
            {
                return previousCode;
            }
            else 
            {
                InternalPrimitiveTypeE code = Converter.ToCode(type); 
                if (code != InternalPrimitiveTypeE.Invalid) 
                {
                    previousType = type; 
                    previousCode = code;
                }
                return code;
            } 
        }
 
 
        private Hashtable assemblyToIdTable = null;
        private long GetAssemblyId(WriteObjectInfo objectInfo) 
        {
            //use objectInfo to get assembly string with new criteria
            SerTrace.Log( this, "GetAssemblyId Entry ",objectInfo.objectType," isSi ",objectInfo.isSi);
            if (assemblyToIdTable == null) 
                assemblyToIdTable = new Hashtable(5);
 
            long assemId = 0; 
            bool isNew = false;
            String assemblyString = objectInfo.GetAssemblyString(); 
            String serializedAssemblyString = assemblyString;
            if (assemblyString.Length == 0)
            {
                assemId = 0; 
            }
            else if (assemblyString.Equals(Converter.urtAssemblyString)) 
            { 
                // Urt type is an assemId of 0. No assemblyString needs
                // to be sent 
                SerTrace.Log( this, "GetAssemblyId urt Assembly String ");
                assemId = 0;
            }
            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 = InternalGetId("___AssemblyString___"+assemblyString, false, null, out isNew); 
                    assemblyToIdTable[assemblyString] = assemId;
                }

            serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, serializedAssemblyString, (int)assemId, isNew, false); 
            }
            SerTrace.Log( this, "GetAssemblyId Exit id ",assemId," isNew ",isNew," assemblyString ",serializedAssemblyString); 
            return assemId; 
        }
 
        private Type GetType(Object obj)
        {
            Type type = null;
            if (RemotingServices.IsTransparentProxy(obj)) 
                type = Converter.typeofMarshalByRefObject;
            else 
                type = obj.GetType(); 
            return type;
        } 

        private SerStack niPool = new SerStack("NameInfo Pool");

        private NameInfo GetNameInfo() 
        {
            NameInfo nameInfo = null; 
 
            if (!niPool.IsEmpty())
            { 
                nameInfo = (NameInfo)niPool.Pop();
                nameInfo.Init();
            }
            else 
                nameInfo = new NameInfo();
 
            return nameInfo; 
        }
 
        private bool CheckTypeFormat(FormatterTypeStyle test, FormatterTypeStyle want)
        {
            return(test & want) == want;
        } 

        private void PutNameInfo(NameInfo nameInfo) 
        { 
            niPool.Push(nameInfo);
        } 

    }
}
 

 
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
 ** 
 ** Class: ObjectWriter 
 **
 ** 
 ** Purpose: Serializes an object graph into XML in SOAP format
 **
 **
 ===========================================================*/ 

namespace System.Runtime.Serialization.Formatters.Binary 
{ 
    using System;
    using System.IO; 
    using System.Reflection;
    using System.Reflection.Cache;
    using System.Collections;
    using System.Collections.Generic; 
    using System.Text;
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Messaging; 
    using System.Runtime.Serialization;
    using System.Security.Permissions; 
    using System.Security;
    using System.Diagnostics;
    using System.Globalization;
 
    internal sealed  class ObjectWriter
    { 
        private Queue m_objectQueue; 
        private ObjectIDGenerator m_idGenerator;
        private int m_currentId; 

        private ISurrogateSelector m_surrogates;
        private StreamingContext m_context;
        private __BinaryWriter serWriter; 
        private SerializationObjectManager m_objectManager;
 
        private long topId; 
        private String topName = null;
        private Header[] headers; 

        private InternalFE formatterEnums;

        private SerObjectInfoInit serObjectInfoInit = null; 

        private IFormatterConverter m_formatterConverter; 
 
        internal Object[] crossAppDomainArray = null;
        internal ArrayList internalCrossAppDomainArray = null; 

        // XMLObjectWriter Constructor
        internal ObjectWriter(ISurrogateSelector selector, StreamingContext context,InternalFE formatterEnums)
        { 
            m_currentId = 1;
            m_surrogates = selector; 
            m_context = context; 
            this.formatterEnums = formatterEnums;
            m_objectManager = new SerializationObjectManager(context); 
            SerTrace.InfoLog(
                            formatterEnums.FEtypeFormat +" "+
                            ((Enum)formatterEnums.FEserializerTypeEnum));
 

        } 
 
        // Commences the process of serializing the entire graph.
        // initialize the graph walker. 
        internal void Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, bool fCheck)
        {
            SerTrace.Log( this, "Serialize Entry 2 ",graph,((headers == null)?" no headers ": "headers "));
 
            if (fCheck)
            { 
                CodeAccessPermission.DemandInternal(PermissionType.SecuritySerialization); 
            }
 
            if (graph == null)
                throw new ArgumentNullException("graph",Environment.GetResourceString("ArgumentNull_Graph"));

            if (serWriter == null) 
                throw new ArgumentNullException("serWriter",String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentNull_WithParamName"), "serWriter"));
 
            this.serWriter = serWriter; 
            this.headers = inHeaders;
 
            SerTrace.Log( this, "Serialize New SerializedTypeTable");
            serWriter.WriteBegin();
            long headerId = 0;
            Object obj; 
            long objectId;
            bool isNew; 
            bool bMethodCall = false; 
            bool bMethodReturn = false;
 
            // Special case IMethodCallMessage and IMethodReturnMessage for performance
            IMethodCallMessage mess = graph as IMethodCallMessage;
            if (mess != null)
            { 
                bMethodCall = true;
                graph = WriteMethodCall(mess); 
            } 
            else
            { 
                IMethodReturnMessage mr = graph as IMethodReturnMessage;
                if (mr != null)
                {
                    bMethodReturn = true; 
                    graph = WriteMethodReturn(mr);
                } 
            } 

            if (graph == null) 
            {
                WriteSerializedStreamHeader(topId, headerId);

                if (bMethodCall) 
                    serWriter.WriteMethodCall();
                else if (bMethodReturn) 
                    serWriter.WriteMethodReturn(); 

                serWriter.WriteSerializationHeaderEnd(); 
                serWriter.WriteEnd();
                return;
            }
 
            // allocations if methodCall or methodResponse and no graph
            m_idGenerator = new ObjectIDGenerator(); 
            m_objectQueue = new Queue(); 
            m_formatterConverter = new FormatterConverter();
            serObjectInfoInit = new SerObjectInfoInit(); 

            topId = InternalGetId(graph, false, null, out isNew);

 
            if (headers != null)
                headerId = InternalGetId(headers, false, null, out isNew); 
            else 
                headerId = -1;
 
            WriteSerializedStreamHeader(topId, headerId);


            if (bMethodCall) 
                serWriter.WriteMethodCall();
            else if (bMethodReturn) 
                serWriter.WriteMethodReturn(); 

 
            SerTrace.Log( this, "Serialize Schedule 0");

            // Write out SerializedStream header
            if ((headers != null) && (headers.Length > 0)) 
                m_objectQueue.Enqueue(headers);
 
            if (graph != null) 
                m_objectQueue.Enqueue(graph);
 
            while ((obj = GetNext(out objectId))!=null)
            {
                SerTrace.Log( 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)
                { 
                    SerTrace.Log( this, "Serialize GetNext recognizes WriteObjectInfo");
                    objectInfo = (WriteObjectInfo)obj;
                }
                else 
                {
                    objectInfo = WriteObjectInfo.Serialize(obj, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter, this); 
                    objectInfo.assemId = GetAssemblyId(objectInfo); 
                }
 

                objectInfo.objectId = objectId;
                NameInfo typeNameInfo = TypeToNameInfo(objectInfo);
                Write(objectInfo, typeNameInfo, typeNameInfo); 
                PutNameInfo(typeNameInfo);
                objectInfo.ObjectEnd(); 
            } 

            serWriter.WriteSerializationHeaderEnd(); 
            serWriter.WriteEnd();

            // Invoke OnSerialized Event
            m_objectManager.RaiseOnSerializedEvent(); 

            SerTrace.Log( this, "Serialize Exit "); 
        } 

        private Object[] WriteMethodCall(IMethodCallMessage mcm) 
        {
            // In header
            String uri = mcm.Uri;
            String methodName = mcm.MethodName; 
            String typeName = mcm.TypeName;
 
            // Optional 
            Object methodSignature = null;
            Object callContext = null; 
            Object[] properties = null;

            // instantiation args
            Type[] instArgs = null; 
            if (mcm.MethodBase.IsGenericMethod)
                instArgs = mcm.MethodBase.GetGenericArguments(); 
 
            // args
            Object[] args = mcm.Args; 

            IInternalMessage iim = mcm as IInternalMessage;

            // user properties (everything but special entries) 
            if ((iim == null) || iim.HasProperties())
                properties = StoreUserPropertiesForMethodMessage(mcm); 
 
            // handle method signature
            if (mcm.MethodSignature != null && RemotingServices.IsMethodOverloaded(mcm)) 
                methodSignature = mcm.MethodSignature;

            // handle call context
            LogicalCallContext lcc = mcm.LogicalCallContext; 
            if (lcc == null)
            { 
                callContext = null; 
            }
            else if (lcc.HasInfo) 
                callContext = lcc;
            else
            {
                // just smuggle the call id string 
                callContext = lcc.RemotingData.LogicalCallID;
            } 
 
            return serWriter.WriteCallArray(uri, methodName, typeName, instArgs, args, methodSignature, callContext, properties);
        } 


        private Object[] WriteMethodReturn(IMethodReturnMessage mrm)
        { 
            Object    returnValue = mrm.ReturnValue;
            Object[]  args = mrm.Args; 
            Exception exception = mrm.Exception; 
            Object callContext;
            Object[] properties = null; 

            ReturnMessage retMsg = mrm as ReturnMessage;

            // user properties (everything but special entries) 
            if ((retMsg == null) || retMsg.HasProperties())
                properties = StoreUserPropertiesForMethodMessage(mrm); 
 
            // handle call context
            LogicalCallContext lcc = mrm.LogicalCallContext; 
            if (lcc == null)
            {
                callContext = null;
            } 
            else if (lcc.HasInfo)
                callContext = lcc; 
            else 
            {
                // just smuggle the call id string 
                callContext = lcc.RemotingData.LogicalCallID;
            }

           return serWriter.WriteReturnArray(returnValue, args, exception, callContext, properties); 
        }
 
        // returns number of entries added to argsToSerialize 
        private static Object[] StoreUserPropertiesForMethodMessage(IMethodMessage msg)
        { 
            ArrayList argsToSerialize = null;
            IDictionary properties = msg.Properties;

            if (properties == null) 
                return null;
 
            MessageDictionary dict = properties as MessageDictionary; 
            if (dict != null)
            { 
                if (dict.HasUserData())
                {
                    int co = 0;
                    foreach (DictionaryEntry entry in dict.InternalDictionary) 
                    {
                        if (argsToSerialize == null) 
                            argsToSerialize = new ArrayList(); 
                        argsToSerialize.Add(entry);
                        co++; 
                    }

                    return argsToSerialize.ToArray();
                } 
                else
                { 
                    return null; 
                }
            } 
            else
            {
                // <
 

                int co = 0; 
                foreach (DictionaryEntry entry in properties) 
                {
                    if (argsToSerialize == null) 
                        argsToSerialize = new ArrayList();
                    argsToSerialize.Add(entry);
                    co++;
                } 

                if (argsToSerialize != null) 
                    return argsToSerialize.ToArray(); 
                else
                    return null; 
            }

        } // StoreUserPropertiesForMethodMessage
 
        internal SerializationObjectManager ObjectManager
        { 
            get { return m_objectManager; } 
        }
 
        // Writes a given object to the stream.
        private void Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
        {
#if _DEBUG 
            SerTrace.Log( this, "Write 1 Entry objectInfo ",objectInfo,", memberNameInfo ",memberNameInfo,", typeNameInfo ",typeNameInfo);
            memberNameInfo.Dump("Write memberNameInfo"); 
            typeNameInfo.Dump("Write typeNameInfo"); 
#endif
            Object obj = objectInfo.obj; 
            if (obj==null)
                throw new ArgumentNullException("objectInfo.obj", Environment.GetResourceString("ArgumentNull_Obj"));

            SerTrace.Log( this, "Write 1 objectInfo obj ",objectInfo.obj," objectId ", objectInfo.objectId, " objectType ", objectInfo.objectType); 
            Type objType = objectInfo.objectType;
            long objectId = objectInfo.objectId; 
 

            SerTrace.Log( this, "Write 1 ",obj," ObjectId ",objectId); 

            if (objType == Converter.typeofString)
            {
                // Top level String 
                memberNameInfo.NIobjectId = objectId;
                serWriter.WriteObjectString((int)objectId, obj.ToString()); 
            } 
            else
            { 

                if (objectInfo.isArray)
                {
                    WriteArray(objectInfo, memberNameInfo, null); 
                }
                else 
                { 
                    String[] memberNames;
                    Type[] memberTypes; 
                    Object[] memberData;

                    objectInfo.GetMemberInfo(out memberNames, out memberTypes, out memberData);
 
                    // 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 (objectInfo.isSi || CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways)) 
                    {
                        SerTrace.Log( 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 0)
                { 
                    // Array as object
                    SerTrace.Log( this, "WriteMembers Schedule 3"); 
                    memberNameInfo.NIobjectId = arrayId; 
                    WriteObjectRef(memberNameInfo, arrayId);
                } 
                else
                {
                    // Nested Array
                    serWriter.WriteMemberNested(memberNameInfo); 

                    memberObjectInfo.objectId = arrayId; 
                    memberNameInfo.NIobjectId = arrayId; 
                    WriteArray(memberObjectInfo, memberNameInfo, memberObjectInfo);
                    objectInfo.ObjectEnd(); 

                }
                SerTrace.Log( this, "WriteMembers Array Exit ");
                return; 
            }
 
            if (!WriteKnownValueClass(memberNameInfo, memberTypeNameInfo, memberData)) 
            {
                SerTrace.Log( this, "WriteMembers Object ",memberData); 

#if false
                // Value or NO_ID, need to explicitly check for IsValue because a top level
                // value class has an objectId of 1 
                /*
                if (memberType.IsValueType) 
                { 
                    SerTrace.Log( this, "WriteMembers Value Type or NO_ID parameter");
 
                    bool isNew;
                    memberObjectInfo.objectId = InternalGetId(outObj, assignUniqueIdToValueType, memberType, out isNew) ;
                    NameInfo newTypeNameInfo = TypeToNameInfo(memberObjectInfo);
                    newTypeNameInfo.NIobjectId = memberObjectInfo.objectId; 
                    Write( memberObjectInfo, memberNameInfo, newTypeNameInfo);
                    PutNameInfo(newTypeNameInfo); 
                    memberObjectInfo.ObjectEnd(); 
                }
                else 
                */
#endif
                {
                    SerTrace.Log( this, "WriteMembers Schedule 4 ", outType, " memberInfo ",memberObjectInfo); 
                    if (outType == null)
                        outType = GetType(outObj); 
                    long memberObjectId = Schedule(outObj, assignUniqueIdToValueType, outType, memberObjectInfo); 
                    if (memberObjectId < 0)
                    { 
                        // Nested object
                        SerTrace.Log( this, "WriteMembers Nesting");

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

            SerTrace.Log( this, "WriteMembers Exit ");
        }
 
        // Writes out an array
        private void WriteArray(WriteObjectInfo objectInfo, NameInfo memberNameInfo, WriteObjectInfo memberObjectInfo) 
        { 
            SerTrace.Log( this, "WriteArray Entry ",objectInfo.obj," ",objectInfo.objectId);
 
            bool isAllocatedMemberNameInfo = false;
            if (memberNameInfo == null)
            {
                memberNameInfo = TypeToNameInfo(objectInfo); 
                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 = null;
            if (!arrayElemType.IsPrimitive)
            { 
                arrayElemObjectInfo = WriteObjectInfo.Serialize(arrayElemType, m_surrogates, m_context, serObjectInfoInit, m_formatterConverter);
                arrayElemObjectInfo.assemId = GetAssemblyId(arrayElemObjectInfo); 
            } 

 
            NameInfo arrayElemTypeNameInfo = null;
            if (arrayElemObjectInfo == null)
                arrayElemTypeNameInfo = TypeToNameInfo(arrayElemType);
            else 
                arrayElemTypeNameInfo = TypeToNameInfo(arrayElemObjectInfo);
            arrayElemTypeNameInfo.NIisArray = arrayElemTypeNameInfo.NItype.IsArray; 
 
            NameInfo arrayNameInfo = memberNameInfo;
            arrayNameInfo.NIobjectId = objectId; 
            arrayNameInfo.NIisArray = true;
            arrayElemTypeNameInfo.NIobjectId = objectId;
            arrayElemTypeNameInfo.NItransmitTypeOnMember = memberNameInfo.NItransmitTypeOnMember;
            arrayElemTypeNameInfo.NItransmitTypeOnObject = memberNameInfo.NItransmitTypeOnObject; 
            arrayElemTypeNameInfo.NIisParentTypeOnObject = memberNameInfo.NIisParentTypeOnObject;
 
            // Get rank and length information 
            int rank = array.Rank;
            int[] lengthA = new int[rank]; 
            int[] lowerBoundA = new int[rank];
            int[] upperBoundA = new int[rank];
            for (int i=0; i-1; irank--) 
                {
                    // Find the current or lower dimension which can be incremented.
                    if (currentA[irank] < maxA[irank]-1)
                    { 
                        // The current dimension is at maximum. Increase the next lower dimension by 1
                        currentA[irank]++; 
                        if (irank < rank-1) 
                        {
                            // The current dimension and higher dimensions are zeroed. 
                            for (int i = irank+1; i 0)
            { 
                if (objectInfo == null)
                    m_objectQueue.Enqueue(obj);
                else
                    m_objectQueue.Enqueue(objectInfo); 

            } 
 
            SerTrace.Log( 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) 
        { 
#if _DEBUG
            SerTrace.Log( this, "WriteKnownValueClass Entry ",typeNameInfo.NIname," ",data," ",memberNameInfo.NIname); 
            memberNameInfo.Dump("WriteKnownValueClass memberNameInfo");
            typeNameInfo.Dump("WriteKnownValueClass typeNameInfo");
#endif
 
            if (typeNameInfo.NItype == Converter.typeofString)
            { 
                WriteString(memberNameInfo, typeNameInfo, data); 
            }
            else 
            {
                if (typeNameInfo.NIprimitiveTypeEnum == InternalPrimitiveTypeE.Invalid)
                {
                    SerTrace.Log( this, "WriteKnownValueClass Exit false"); 
                    return false;
                } 
                else 
                {
                    if (typeNameInfo.NIisArray) // null if an array 
                        serWriter.WriteItem(memberNameInfo, typeNameInfo, data);
                    else
                    {
                        serWriter.WriteMember(memberNameInfo, typeNameInfo, data); 
                    }
                } 
            } 

            SerTrace.Log( this, "WriteKnownValueClass Exit true"); 
            return true;
        }

 
        // Writes an object reference to the stream.
        private void WriteObjectRef(NameInfo nameInfo, long objectId) 
        { 
            SerTrace.Log( this, "WriteObjectRef Entry ",nameInfo.NIname," ",objectId);
            serWriter.WriteMemberObjectRef(nameInfo, (int)objectId); 

            SerTrace.Log( this, "WriteObjectRef Exit ");
        }
 

 
        // Writes a string into the XML stream 
        private void WriteString(NameInfo memberNameInfo, NameInfo typeNameInfo, Object stringObject)
        { 
            SerTrace.Log( this, "WriteString stringObject ",stringObject," memberName ",memberNameInfo.NIname);
            bool isFirstTime = true;

            long stringId = -1; 

            if (!CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.XsdString)) 
                stringId= InternalGetId(stringObject, false, null, out isFirstTime); 

            typeNameInfo.NIobjectId = stringId; 
            SerTrace.Log( this, "WriteString stringId ",stringId," isFirstTime ",isFirstTime);

            if ((isFirstTime) || (stringId < 0))
                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)
        {
#if _DEBUG
            SerTrace.Log( this, "CheckForNull Entry data ",Util.PString(data),", memberType ",Util.PString(typeNameInfo.NItype)); 
#endif
            bool isNull = false; 
 
            if (data == null) // || Convert.IsDBNull(data)
                isNull = true; 

            // Optimization, Null members are only written for Binary
            if ((isNull) && (((formatterEnums.FEserializerTypeEnum == InternalSerializerTypeE.Binary)) ||
                             memberNameInfo.NIisArrayItem || 
                             memberNameInfo.NItransmitTypeOnObject ||
                             memberNameInfo.NItransmitTypeOnMember || 
                             objectInfo.isSi || 
                             (CheckTypeFormat(formatterEnums.FEtypeFormat, FormatterTypeStyle.TypesAlways))))
            { 
                SerTrace.Log( this, "CheckForNull Write");

                if (typeNameInfo.NIisArrayItem)
                { 
                    if (typeNameInfo.NIarrayEnum == InternalArrayTypeE.Single)
                        serWriter.WriteDelayedNullItem(); 
                    else 
                        serWriter.WriteNullItem(memberNameInfo, typeNameInfo);
                } 

                else
                    serWriter.WriteNullMember(memberNameInfo, typeNameInfo);
            } 
            SerTrace.Log( 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) 
        {
            SerTrace.Log( this, "TypeToNameInfo Entry type ",type,", objectInfo ",objectInfo,", code ", ((Enum)code).ToString());
            if (nameInfo == null)
                nameInfo = GetNameInfo(); 
            else
                nameInfo.Init(); 
 
            if (code == InternalPrimitiveTypeE.Invalid)
            { 
                if (objectInfo != null)
                {
                    nameInfo.NIname = objectInfo.GetTypeFullName();
                    nameInfo.NIassemId = objectInfo.assemId; 
                }
            } 
            nameInfo.NIprimitiveTypeEnum = code; 
            nameInfo.NItype = type;
 
            SerTrace.Log( this, "TypeToNameInfo Exit ",type, " typeName "+nameInfo.NIname);
            return nameInfo;
        }
 
        private NameInfo TypeToNameInfo(Type type)
        { 
            return TypeToNameInfo(type, null, ToCode(type), null); 
        }
 
        private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo)
        {
            return TypeToNameInfo(objectInfo.objectType, objectInfo, ToCode(objectInfo.objectType), null);
        } 

        private NameInfo TypeToNameInfo(WriteObjectInfo objectInfo, NameInfo nameInfo) 
        { 
            return TypeToNameInfo(objectInfo.objectType, objectInfo, ToCode(objectInfo.objectType), nameInfo);
        } 

        private void TypeToNameInfo(Type type, NameInfo nameInfo)
        {
            TypeToNameInfo(type, null, ToCode(type), nameInfo); 
        }
 
        private NameInfo MemberToNameInfo(String name) 
        {
            NameInfo memberNameInfo = GetNameInfo(); 
            memberNameInfo.NIname = name;
            return memberNameInfo;
        }
 
        Type previousType = null;
        InternalPrimitiveTypeE previousCode = InternalPrimitiveTypeE.Invalid; 
        internal InternalPrimitiveTypeE ToCode(Type type) 
        {
            if (previousType == type) 
            {
                return previousCode;
            }
            else 
            {
                InternalPrimitiveTypeE code = Converter.ToCode(type); 
                if (code != InternalPrimitiveTypeE.Invalid) 
                {
                    previousType = type; 
                    previousCode = code;
                }
                return code;
            } 
        }
 
 
        private Hashtable assemblyToIdTable = null;
        private long GetAssemblyId(WriteObjectInfo objectInfo) 
        {
            //use objectInfo to get assembly string with new criteria
            SerTrace.Log( this, "GetAssemblyId Entry ",objectInfo.objectType," isSi ",objectInfo.isSi);
            if (assemblyToIdTable == null) 
                assemblyToIdTable = new Hashtable(5);
 
            long assemId = 0; 
            bool isNew = false;
            String assemblyString = objectInfo.GetAssemblyString(); 
            String serializedAssemblyString = assemblyString;
            if (assemblyString.Length == 0)
            {
                assemId = 0; 
            }
            else if (assemblyString.Equals(Converter.urtAssemblyString)) 
            { 
                // Urt type is an assemId of 0. No assemblyString needs
                // to be sent 
                SerTrace.Log( this, "GetAssemblyId urt Assembly String ");
                assemId = 0;
            }
            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 = InternalGetId("___AssemblyString___"+assemblyString, false, null, out isNew); 
                    assemblyToIdTable[assemblyString] = assemId;
                }

            serWriter.WriteAssembly(objectInfo.GetTypeFullName(), objectInfo.objectType, serializedAssemblyString, (int)assemId, isNew, false); 
            }
            SerTrace.Log( this, "GetAssemblyId Exit id ",assemId," isNew ",isNew," assemblyString ",serializedAssemblyString); 
            return assemId; 
        }
 
        private Type GetType(Object obj)
        {
            Type type = null;
            if (RemotingServices.IsTransparentProxy(obj)) 
                type = Converter.typeofMarshalByRefObject;
            else 
                type = obj.GetType(); 
            return type;
        } 

        private SerStack niPool = new SerStack("NameInfo Pool");

        private NameInfo GetNameInfo() 
        {
            NameInfo nameInfo = null; 
 
            if (!niPool.IsEmpty())
            { 
                nameInfo = (NameInfo)niPool.Pop();
                nameInfo.Init();
            }
            else 
                nameInfo = new NameInfo();
 
            return nameInfo; 
        }
 
        private bool CheckTypeFormat(FormatterTypeStyle test, FormatterTypeStyle want)
        {
            return(test & want) == want;
        } 

        private void PutNameInfo(NameInfo nameInfo) 
        { 
            niPool.Push(nameInfo);
        } 

    }
}
 

 
 

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

Link Menu

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