BinaryObjectReader.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 / 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 System.Runtime.CompilerServices;
    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 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