BinaryObjectReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / Serialization / Formatters / Binary / BinaryObjectReader.cs / 1 / BinaryObjectReader.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
 ** 
 ** Class: ObjectReader 
 **
 ** 
 ** Purpose: DeSerializes Binary Wire format
 **
 **
 ===========================================================*/ 

namespace System.Runtime.Serialization.Formatters.Binary { 
 
    using System;
    using System.Globalization; 
    using System.IO;
    using System.Reflection;
    using System.Collections;
    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.Resources;
    using StackCrawlMark = System.Threading.StackCrawlMark;
 
    internal sealed class ObjectReader
    { 
 
        // System.Serializer information
        internal Stream m_stream; 
        internal ISurrogateSelector m_surrogates;
        internal StreamingContext m_context;
        internal ObjectManager m_objectManager;
        internal InternalFE formatterEnums; 
        internal SerializationBinder m_binder;
 
        // Top object and headers 
        internal long topId;
        internal bool bSimpleAssembly = false; 
        internal Object handlerObject;
        internal Object m_topObject;
        internal Header[] headers;
        internal HeaderHandler handler; 
        internal SerObjectInfoInit serObjectInfoInit;
        internal IFormatterConverter m_formatterConverter; 
 
        // Stack of Object ParseRecords
        internal SerStack stack; 

        // ValueType Fixup Stack
        private SerStack valueFixupStack;
 
        // Cross AppDomain
        internal Object[] crossAppDomainArray; //Set by the BinaryFormatter 
 
        //MethodCall and MethodReturn are handled special for perf reasons
        private bool bMethodCall; 
        private bool bMethodReturn;
        private bool bFullDeserialization;
        private BinaryMethodCall binaryMethodCall;
        private BinaryMethodReturn binaryMethodReturn; 
        private bool bIsCrossAppDomain;
 
        private Exception deserializationSecurityException; 
        private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
 
        private SerStack ValueFixupStack
        {
            get {
                if (valueFixupStack == null) 
                    valueFixupStack = new SerStack("ValueType Fixup Stack");
                return valueFixupStack; 
            } 
        }
 
        internal Object TopObject{
            get {
                return m_topObject;
            } 
            set {
                m_topObject = value; 
                if (m_objectManager != null) 
                    m_objectManager.TopObject = value;
            } 
        }

        internal void SetMethodCall(BinaryMethodCall binaryMethodCall)
        { 
            bMethodCall = true;
            this.binaryMethodCall = binaryMethodCall; 
        } 

        internal void SetMethodReturn(BinaryMethodReturn binaryMethodReturn) 
        {
            bMethodReturn = true;
            this.binaryMethodReturn = binaryMethodReturn;
        } 

 
        internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder) 
        {
            SerTrace.Log( this, "Constructor ISurrogateSelector ",((selector == null)?"null selector ":"selector present")); 

            if (stream==null)
            {
                throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream")); 
            }
 
            m_stream=stream; 
            m_surrogates = selector;
            m_context = context; 
            m_binder =  binder;

#if !FEATURE_PAL
            // This is a hack to allow us to write a type-limiting deserializer 
            // when we know exactly what type to expect at the head of the
            // object graph. 
            if (m_binder != null) { 
                ResourceReader.TypeLimitingDeserializationBinder tldBinder = m_binder as ResourceReader.TypeLimitingDeserializationBinder;
                if (tldBinder != null) 
                    tldBinder.ObjectReader = this;
            }
#endif // !FEATURE_PAL
 
            this.formatterEnums = formatterEnums;
 
            //SerTrace.Log( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject); 

        } 

        // Deserialize the stream into an object graph.
        internal Object Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck, bool isCrossAppDomain, IMethodCallMessage methodCallMessage)
        { 
#if _DEBUG
            SerTrace.Log( this, "Deserialize Entry handler", handler); 
#endif 
            bFullDeserialization = false;
            bMethodCall = false; 
            bMethodReturn = false;
            TopObject = null;
            topId = 0;
            bIsCrossAppDomain = isCrossAppDomain; 
            bSimpleAssembly =  (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple);
 
            if (serParser == null) 
                throw new ArgumentNullException("serParser", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentNull_WithParamName"), serParser));
 
            if (fCheck)
            {
                try{
                    CodeAccessPermission.DemandInternal(PermissionType.SecuritySerialization); 
                }catch(Exception e)
                { 
                    deserializationSecurityException = e; 
                }
            } 

            this.handler = handler;

 
            if (bFullDeserialization)
            { 
                // Reinitialize 
                m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
                serObjectInfoInit = new SerObjectInfoInit(); 
            }

            // Will call back to ParseObject, ParseHeader for each object found
            serParser.Run(); 

#if _DEBUG 
            SerTrace.Log( this, "Deserialize Finished Parsing DoFixups"); 
#endif
 
            if (bFullDeserialization)
                m_objectManager.DoFixups();

 
            if (!bMethodCall && !bMethodReturn)
            { 
                if (TopObject == null) 
                    throw new SerializationException(Environment.GetResourceString("Serialization_TopObject"));
 
                //if TopObject has a surrogate then the actual object may be changed during special fixup
                //So refresh it using topID.
                if (HasSurrogate(TopObject.GetType())  && topId != 0)//Not yet resolved
                    TopObject = m_objectManager.GetObject(topId); 

                if (TopObject is IObjectReference) 
                { 
                    TopObject = ((IObjectReference)TopObject).GetRealObject(m_context);
                } 
            }

            SerTrace.Log( this, "Deserialize Exit ",TopObject);
 
            if (bFullDeserialization)
            { 
                m_objectManager.RaiseDeserializationEvent(); // This will raise both IDeserialization and [OnDeserialized] events 
            }
 
            // Return the headers if there is a handler
            if (handler != null)
            {
                handlerObject = handler(headers); 
            }
 
            if (bMethodCall) 
            {
                Object[] methodCallArray = TopObject as Object[]; 
                TopObject = binaryMethodCall.ReadArray(methodCallArray, handlerObject);
            }
            else if (bMethodReturn)
            { 
                Object[] methodReturnArray = TopObject as Object[];
                TopObject = binaryMethodReturn.ReadArray(methodReturnArray, methodCallMessage, handlerObject); 
            } 

            return TopObject; 
        }

        private bool HasSurrogate(Type t){
            if (m_surrogates == null) 
                return false;
            ISurrogateSelector notUsed; 
            return m_surrogates.GetSurrogate(t, m_context, out notUsed) != null; 
        }
 
        private void CheckSerializable(Type t)
        {
            if (!t.IsSerializable && !HasSurrogate(t))
                throw new SerializationException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Serialization_NonSerType"), 
                                                                     t.FullName, t.Assembly.FullName));
        } 
 
        private void InitFullDeserialization()
        { 
            bFullDeserialization = true;
            stack = new SerStack("ObjectReader Object Stack");

            m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain); 
            if (m_formatterConverter == null)
                m_formatterConverter = new FormatterConverter(); 
        } 

 
        internal Object CrossAppDomainArray(int index)
        {
            BCLDebug.Assert((index < crossAppDomainArray.Length),
                             "[System.Runtime.Serialization.Formatters.BinaryObjectReader index out of range for CrossAppDomainArray]"); 
            return crossAppDomainArray[index];
        } 
 
        internal ReadObjectInfo CreateReadObjectInfo(Type objectType)
        { 
            return ReadObjectInfo.Create(objectType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
        }

        internal ReadObjectInfo CreateReadObjectInfo(Type objectType, String[] memberNames, Type[] memberTypes) 
        {
            return ReadObjectInfo.Create(objectType, memberNames, memberTypes, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly); 
        } 

 
        // Main Parse routine, called by the XML Parse Handlers in XMLParser and also called internally to
        internal void Parse(ParseRecord pr)
        {
#if _DEBUG 
            SerTrace.Log( this, "Parse");
            stack.Dump(); 
            pr.Dump(); 
#endif
 
            switch (pr.PRparseTypeEnum)
            {
                case InternalParseTypeE.SerializedStreamHeader:
                    ParseSerializedStreamHeader(pr); 
                    break;
                case InternalParseTypeE.SerializedStreamHeaderEnd: 
                    ParseSerializedStreamHeaderEnd(pr); 
                    break;
                case InternalParseTypeE.Object: 
                    ParseObject(pr);
                    break;
                case InternalParseTypeE.ObjectEnd:
                    ParseObjectEnd(pr); 
                    break;
                case InternalParseTypeE.Member: 
                    ParseMember(pr); 
                    break;
                case InternalParseTypeE.MemberEnd: 
                    ParseMemberEnd(pr);
                    break;
                case InternalParseTypeE.Body:
                case InternalParseTypeE.BodyEnd: 
                case InternalParseTypeE.Envelope:
                case InternalParseTypeE.EnvelopeEnd: 
                    break; 
                case InternalParseTypeE.Empty:
                default: 
                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_XMLElement"), pr.PRname));

            }
        } 

 
        // Styled ParseError output 
        private void ParseError(ParseRecord processing, ParseRecord onStack)
        { 
#if _DEBUG
            SerTrace.Log( this, " ParseError ",processing," ",onStack);
#endif
            throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ParseError"),onStack.PRname+" "+((Enum)onStack.PRparseTypeEnum) + " "+processing.PRname+" "+((Enum)processing.PRparseTypeEnum))); 
        }
 
        // Parse the SerializedStreamHeader element. This is the first element in the stream if present 
        private void ParseSerializedStreamHeader(ParseRecord pr)
        { 
#if _DEBUG
            SerTrace.Log( this, "SerializedHeader ",pr);
#endif
            stack.Push(pr); 
        }
 
        // Parse the SerializedStreamHeader end element. This is the last element in the stream if present 
        private void ParseSerializedStreamHeaderEnd(ParseRecord pr)
        { 
#if _DEBUG
            SerTrace.Log( this, "SerializedHeaderEnd ",pr);
#endif
            stack.Pop(); 
        }
 
        private bool IsRemoting { 
            get {
                //return (m_context.State & (StreamingContextStates.Persistence|StreamingContextStates.File|StreamingContextStates.Clone)) == 0; 
                return (bMethodCall || bMethodReturn);
            }
        }
 
         internal void CheckSecurity(ParseRecord pr)
         { 
            InternalST.SoapAssert(pr!=null, "[BinaryObjectReader.CheckSecurity]pr!=null"); 
            Type t = pr.PRdtType;
            if (t != null){ 
                if( IsRemoting){
                    if (typeof(MarshalByRefObject).IsAssignableFrom(t))
                        throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_MBRAsMBV"), t.FullName));
                    FormatterServices.CheckTypeSecurity(t, formatterEnums.FEsecurityLevel); 
                }
            } 
 
            //If we passed the security check, they can do whatever they'd like,
            //so we'll just short-circuit this. 
            if (deserializationSecurityException==null) {
                return;
            }
 
            // BaseTypes and Array of basetypes allowed
 
            if (t != null) 
            {
                if (t.IsPrimitive || t == Converter.typeofString) 
                    return;

                if (typeof(Enum).IsAssignableFrom(t))
                    return; 

                if (t.IsArray) 
                { 
                    Type type = t.GetElementType();
                    if (type.IsPrimitive || type == Converter.typeofString) 
                        return;
                }
            }
 
            throw deserializationSecurityException;
        } 
 
        // New object encountered in stream
        private void ParseObject(ParseRecord pr) 
        {
#if _DEBUG
            SerTrace.Log( this, "ParseObject Entry ");
#endif 

            if (!bFullDeserialization) 
                InitFullDeserialization(); 

            if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
                topId = pr.PRobjectId;

            if (pr.PRparseTypeEnum == InternalParseTypeE.Object)
            { 
                    stack.Push(pr); // Nested objects member names are already on stack
            } 
 
            if (pr.PRobjectTypeEnum == InternalObjectTypeE.Array)
            { 
                ParseArray(pr);
#if _DEBUG
                SerTrace.Log( this, "ParseObject Exit, ParseArray ");
#endif 
                return;
            } 
 
            // If the Type is null, this means we have a typeload issue
            // mark the object with TypeLoadExceptionHolder 
            if (pr.PRdtType == null)
            {
                pr.PRnewObj = new TypeLoadExceptionHolder(pr.PRkeyDt);
                return; 
            }
 
            if (pr.PRdtType == Converter.typeofString) 
            {
                // String as a top level object 
                if (pr.PRvalue != null)
                {
                    pr.PRnewObj = pr.PRvalue;
                    if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
                    {
#if _DEBUG 
                        SerTrace.Log( this, "ParseObject String as top level, Top Object Resolved"); 
#endif
                        TopObject = pr.PRnewObj; 
                        //stack.Pop();
                        return;
                    }
                    else 
                    {
#if _DEBUG 
                        SerTrace.Log( this, "ParseObject  String as an object"); 
#endif
                        stack.Pop(); 
                        RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());
                        return;
                    }
                } 
                else
                { 
                    // xml Doesn't have the value until later 
                    return;
                } 
            }
            else {
                    CheckSerializable(pr.PRdtType);
                    if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full) 
                        pr.PRnewObj = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);
                    else 
                        pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType); 

                    // Run the OnDeserializing methods 
                    m_objectManager.RaiseOnDeserializingEvent(pr.PRnewObj);
            }

            if (pr.PRnewObj == null) 
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_TopObjectInstantiate"),pr.PRdtType));
 
            if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) 
            {
#if _DEBUG 
                SerTrace.Log( this, "ParseObject  Top Object Resolved ",pr.PRnewObj.GetType());
#endif
                TopObject = pr.PRnewObj;
            } 

            if (pr.PRobjectInfo == null) 
                pr.PRobjectInfo = ReadObjectInfo.Create(pr.PRdtType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly); 

            CheckSecurity(pr); 

#if _DEBUG
            SerTrace.Log( this, "ParseObject Exit ");
#endif 
        }
 
        // End of object encountered in stream 
        private void ParseObjectEnd(ParseRecord pr)
        { 
#if _DEBUG
            SerTrace.Log( this, "ParseObjectEnd Entry ",pr.Trace());
#endif
            ParseRecord objectPr = (ParseRecord)stack.Peek(); 
            if (objectPr == null)
                objectPr = pr; 
 
            //BCLDebug.Assert(objectPr != null, "[System.Runtime.Serialization.Formatters.ParseObjectEnd]objectPr != null");
 
#if _DEBUG
            SerTrace.Log( this, "ParseObjectEnd objectPr ",objectPr.Trace());
#endif
 
            if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
            { 
#if _DEBUG 
                SerTrace.Log( this, "ParseObjectEnd Top Object dtType ",objectPr.PRdtType);
#endif 
                if (objectPr.PRdtType == Converter.typeofString)
                {
#if _DEBUG
                    SerTrace.Log( this, "ParseObjectEnd Top String"); 
#endif
                    objectPr.PRnewObj = objectPr.PRvalue; 
                    TopObject = objectPr.PRnewObj; 
                    return;
                } 
            }

            stack.Pop();
            ParseRecord parentPr = (ParseRecord)stack.Peek(); 

            if (objectPr.PRnewObj == null) 
                return; 

            if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array) 
            {
                if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
                {
#if _DEBUG 
                    SerTrace.Log( this, "ParseObjectEnd  Top Object (Array) Resolved");
#endif 
                    TopObject = objectPr.PRnewObj; 
                }
 
#if _DEBUG
                SerTrace.Log( this, "ParseArray  RegisterObject ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType());
#endif
                RegisterObject(objectPr.PRnewObj, objectPr, parentPr); 

                return; 
            } 

            objectPr.PRobjectInfo.PopulateObjectMembers(objectPr.PRnewObj, objectPr.PRmemberData); 

            // Registration is after object is populated
            if ((!objectPr.PRisRegistered) && (objectPr.PRobjectId > 0))
            { 
#if _DEBUG
                SerTrace.Log( this, "ParseObject Register Object ",objectPr.PRobjectId," ",objectPr.PRnewObj.GetType()); 
#endif 
                RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
            } 

            if (objectPr.PRisValueTypeFixup)
            {
#if _DEBUG 
                SerTrace.Log( this, "ParseObjectEnd  ValueTypeFixup ",objectPr.PRnewObj.GetType());
#endif 
                ValueFixup fixup = (ValueFixup)ValueFixupStack.Pop(); //Value fixup 
                fixup.Fixup(objectPr, parentPr);  // Value fixup
 
            }

            if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top)
            { 
#if _DEBUG
                SerTrace.Log( this, "ParseObjectEnd  Top Object Resolved ",objectPr.PRnewObj.GetType()); 
#endif 
                TopObject = objectPr.PRnewObj;
            } 

            objectPr.PRobjectInfo.ObjectEnd();

#if _DEBUG 
            SerTrace.Log( this, "ParseObjectEnd  Exit ",objectPr.PRnewObj.GetType()," id: ",objectPr.PRobjectId);
#endif 
        } 

 

        // Array object encountered in stream
        private void ParseArray(ParseRecord pr)
        { 
            SerTrace.Log( this, "ParseArray Entry");
 
            long genId = pr.PRobjectId; 

            if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) 
            {
                SerTrace.Log( this, "ParseArray bin.base64 ",pr.PRvalue.Length," ",pr.PRvalue);
                // ByteArray
                if (pr.PRvalue.Length > 0) 
                    pr.PRnewObj = Convert.FromBase64String(pr.PRvalue);
                else 
                    pr.PRnewObj = new Byte[0]; 

                if (stack.Peek() == pr) 
                {
                    SerTrace.Log( this, "ParseArray, bin.base64 has been stacked");
                    stack.Pop();
                } 
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
        { 
                    TopObject = pr.PRnewObj; 
        }
 
                ParseRecord parentPr = (ParseRecord)stack.Peek();

                // Base64 can be registered at this point because it is populated
                SerTrace.Log( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType()); 
                RegisterObject(pr.PRnewObj, pr, parentPr);
 
            } 
            else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))
            { 
                // Primtive typed Array has already been read
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
        {
                    TopObject = pr.PRnewObj; 
        }
 
                ParseRecord parentPr = (ParseRecord)stack.Peek(); 

                // Primitive typed array can be registered at this point because it is populated 
                SerTrace.Log( this, "ParseArray  RegisterObject ",pr.PRobjectId," ",pr.PRnewObj.GetType());
                RegisterObject(pr.PRnewObj, pr, parentPr);
            }
            else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)) 
            {
                // Multidimensional jagged array or single array 
                SerTrace.Log( this, "ParseArray Before Jagged,Simple create ",pr.PRarrayElementType," ",pr.PRlengthA[0]); 
                bool bCouldBeValueType = true;
                if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0)) 
                {
                    if (pr.PRarrayElementType == Converter.typeofString)
                    {
                        pr.PRobjectA = new String[pr.PRlengthA[0]]; 
                        pr.PRnewObj = pr.PRobjectA;
                        bCouldBeValueType = false; 
                    } 
                    else if (pr.PRarrayElementType == Converter.typeofObject)
                    { 
                        pr.PRobjectA = new Object[pr.PRlengthA[0]];
                        pr.PRnewObj = pr.PRobjectA;
                        bCouldBeValueType = false;
                    } 
                    else if (pr.PRarrayElementType != null) {
                        pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA[0]); 
                    } 
                    pr.PRisLowerBound = false;
                } 
                else
                {
                    if (pr.PRarrayElementType != null) {
                        pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA); 
                    }
                    pr.PRisLowerBound = true; 
                } 

                if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single) 
                {
                    if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode)))
                    {
                        pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj); 
                    }
                    else if (bCouldBeValueType && pr.PRarrayElementType != null) 
                    { 
                        if (!pr.PRarrayElementType.IsValueType && !pr.PRisLowerBound)
                            pr.PRobjectA = (Object[])pr.PRnewObj; 
                    }
                }

                SerTrace.Log( this, "ParseArray Jagged,Simple Array ",pr.PRnewObj.GetType()); 

                // For binary, headers comes in as an array of header objects 
                if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers) 
                {
                    SerTrace.Log( this, "ParseArray header array"); 
                    headers = (Header[])pr.PRnewObj;
                }

                pr.PRindexMap = new int[1]; 

            } 
            else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular) 
            {
                // Rectangle array 

                pr.PRisLowerBound = false;
                if (pr.PRlowerBoundA != null)
                { 
                    for (int i=0; i-1; irank--)
            { 
                // Find the current or lower dimension which can be incremented. 
                if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank]-1)
                { 
                    // The current dimension is at maximum. Increase the next lower dimension by 1
                    pr.PRrectangularMap[irank]++;
                    if (irank < pr.PRrank-1)
                    { 
                        // The current dimension and higher dimensions are zeroed.
                        for (int i = irank+1; i 0)
                    NextRectangleMap(objectPr); // Rectangle array, calculate position in array
                if (objectPr.PRisLowerBound)
                { 
                    for (int i=0; i 0))
            {
                SerTrace.Log( this, "ParseString  RegisterObject ",pr.PRvalue," ",pr.PRobjectId);
                // String is treated as an object if it has an id 
                //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId);
                RegisterObject(pr.PRvalue, pr, parentPr, true); 
            } 
        }
 

        private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr)
        {
            RegisterObject(obj, pr, objectPr, false); 
        }
 
        private void RegisterObject(Object obj, ParseRecord pr, ParseRecord objectPr, bool bIsString) 
        {
            if (!pr.PRisRegistered) 
            {
                pr.PRisRegistered = true;

                SerializationInfo si = null; 
                long parentId = 0;
                MemberInfo memberInfo = null; 
                int[] indexMap = null; 

                if (objectPr != null) 
                {
                    indexMap = objectPr.PRindexMap;
                    parentId = objectPr.PRobjectId;
 
                    if (objectPr.PRobjectInfo != null)
                    { 
                        if (!objectPr.PRobjectInfo.isSi) 
                        {
                            // ParentId is only used if there is a memberInfo 

                            memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
                        }
                    } 
                }
                // SerializationInfo is always needed for ISerialization 
                si = pr.PRsi; 

                SerTrace.Log( this, "RegisterObject 0bj ",obj," objectId ",pr.PRobjectId," si ", si," parentId ",parentId," memberInfo ",memberInfo, " indexMap "+indexMap); 
                if (bIsString)
                    m_objectManager.RegisterString((String)obj, pr.PRobjectId, si, parentId, memberInfo);
                else
                    m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap); 
            }
        } 
 

        // Assigns an internal ID associated with the binary id number 

        // Older formatters generate ids for valuetypes using a different counter than ref types. Newer ones use
        // a single counter, only value types have a negative value. Need a way to handle older formats.
        private const int THRESHOLD_FOR_VALUETYPE_IDS = Int32.MaxValue; 
        private bool bOldFormatDetected = false;
        private IntSizedArray   valTypeObjectIdTable; 
 
        internal long GetId(long objectId)
        { 

            if (!bFullDeserialization)
                InitFullDeserialization();
 

            if (objectId > 0) 
                return objectId; 

            if (bOldFormatDetected || objectId == -1) 
            {
                // Alarm bells. This is an old format. Deal with it.
                bOldFormatDetected = true;
                if (valTypeObjectIdTable == null) 
                    valTypeObjectIdTable = new IntSizedArray();
 
                long tempObjId = 0; 
                if ((tempObjId = valTypeObjectIdTable[(int)objectId]) == 0)
                { 
                    tempObjId = THRESHOLD_FOR_VALUETYPE_IDS + objectId;
                    valTypeObjectIdTable[(int)objectId] = (int)tempObjId;
                }
                return tempObjId; 
            }
            return -1 * objectId; 
        } 

 
        // Trace which includes a single dimensional int array
        [Conditional("SER_LOGGING")]
        private void IndexTraceMessage(String message, int[] index)
        { 
            StringBuilder sb = new StringBuilder(10);
            sb.Append("["); 
            for (int i=0; i

                        

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