ObjectManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Runtime / Serialization / ObjectManager.cs / 3 / ObjectManager.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class: ObjectManager 
**
** 
** Purpose:
**
**
============================================================*/ 
namespace System.Runtime.Serialization {
    using System; 
    using System.Collections; 
    using System.Collections.Generic;
    using System.Diagnostics; 
    using System.Reflection;
    using System.Reflection.Cache;
    using System.Runtime.Remoting;
    using System.Security.Permissions; 
    using System.Security;
    using System.Runtime.Remoting.Messaging; 
    using System.Globalization; 

    [System.Runtime.InteropServices.ComVisible(true)] 
    public class ObjectManager {
        private const int DefaultInitialSize=16;
        private const int MaxArraySize=0x1000; //MUST BE A POWER OF 2!
        private const int ArrayMask = MaxArraySize-1; 
        private const int MaxReferenceDepth = 100;
 
        private DeserializationEventHandler m_onDeserializationHandler; 
        private SerializationEventHandler m_onDeserializedHandler;
 
        private static Type[] SIConstructorTypes;
#if !FEATURE_PAL
        private static Type TypeOfWindowsIdentity;
        private static Type[] SIWindowsIdentityConstructorTypes; 
#endif
        internal ObjectHolder []    m_objects; 
        internal Object m_topObject = null; 
        internal ObjectHolderList   m_specialFixupObjects; //This is IObjectReference, ISerializable, or has a Surrogate.
        internal long               m_fixupCount; 
        internal ISurrogateSelector m_selector;
        internal StreamingContext   m_context;
        bool m_isCrossAppDomain;
 
        public ObjectManager(ISurrogateSelector selector, StreamingContext context) : this(selector, context, true, false) {
        } 
 
        internal ObjectManager(ISurrogateSelector selector, StreamingContext context, bool checkSecurity, bool isCrossAppDomain) {
            if (checkSecurity) { 
                CodeAccessPermission.DemandInternal(PermissionType.SecuritySerialization);
            }
            m_objects = new ObjectHolder[DefaultInitialSize];
            m_selector = selector; 
            m_context = context;
            m_isCrossAppDomain = isCrossAppDomain; 
        } 

 
        private bool CanCallGetType(Object obj) {
            if (RemotingServices.IsTransparentProxy(obj)) {
                return false;
            } 
            return true;
        } 
 
        internal Object TopObject {
            set { 
                m_topObject = value;
            }
            get {
                return m_topObject; 
            }
        } 
 
        internal ObjectHolderList SpecialFixupObjects {
            get { 
                if (m_specialFixupObjects==null) {
                    m_specialFixupObjects = new ObjectHolderList();
                }
                return m_specialFixupObjects; 
            }
        } 
 
        static ObjectManager() {
            SIConstructorTypes = new Type[2]; 
            SIConstructorTypes[0] = typeof(SerializationInfo);
            SIConstructorTypes[1] = typeof(StreamingContext);
#if !FEATURE_PAL
            TypeOfWindowsIdentity = typeof(System.Security.Principal.WindowsIdentity); 
            SIWindowsIdentityConstructorTypes = new Type[1];
            SIWindowsIdentityConstructorTypes[0] = typeof(SerializationInfo); 
#endif 
        }
 
        /*==================================FindObject==================================
        **Action: An internal-only function to find the object with id objectID.
        **This function does no error checking, it assumes that all of that has been done already.
        **Returns: The ObjectHolder for objectID or null if it doesn't exist. 
        **Arguments: objectID -- The objectID of the Object for which we're searching.
        **Exceptions: None.  This is internal only. 
        **Callers should verify that objectID is greater than 0. 
        ==============================================================================*/
        internal ObjectHolder FindObjectHolder(long objectID) { 
            BCLDebug.Assert(objectID>0,"objectID>0");

            //The  index of the bin in which we live is rightmost n bits of the objectID.
            int index = (int)(objectID & ArrayMask); 
            if (index>=m_objects.Length) {
                return null; 
            } 

            //Find the bin in which we live. 
            ObjectHolder temp = m_objects[index];

            //Walk the chain in that bin.  Return the ObjectHolder if we find it, otherwise
            //return null. 
            while (temp!=null) {
                if (temp.m_id==objectID) { 
                    return temp; 
                }
                temp = temp.m_next; 
            }
            return temp;
        }
 

        internal ObjectHolder FindOrCreateObjectHolder(long objectID) { 
            ObjectHolder holder; 
            holder = FindObjectHolder(objectID);
            if (holder==null) { 
                holder = new ObjectHolder(objectID);
                AddObjectHolder(holder);
            }
            return holder; 
        }
 
 
        /*===============================AddObjectHolder================================
        **Action: Add the provided ObjectHolder to collection of ObjectHolders. 
        **        Enlarges the collection as appropriate.
        **Returns: void
        **Arguments: holder The ObjectHolder to be added.
        **Exceptions: Internal only.  Caller should verify that holder is 
        **            not null.
        ==============================================================================*/ 
        private void AddObjectHolder(ObjectHolder holder) { 

            BCLDebug.Assert(holder!=null,"holder!=null"); 
            BCLDebug.Trace("SER", "[AddObjectHolder]Adding ObjectHolder with id: ", holder.m_id, " Current Bins: ", m_objects.Length);
            BCLDebug.Assert(holder.m_id>=0,"holder.m_id>=0");

            //If the id that we need to place is greater than our current length, and less 
            //than the maximum allowable size of the array.  We need to double the size
            //of the array.  If the array has already reached it's maximum allowable size, 
            //we chain elements off of the buckets. 
            if (holder.m_id>=m_objects.Length && m_objects.Length != MaxArraySize) {
                int newSize=MaxArraySize; 

                if (holder.m_id<(MaxArraySize/2)) {
                    newSize = (m_objects.Length * 2);
 
                    //Keep doubling until we're larger than our target size.
                    //We could also do this with log operations, but that would 
                    //be slower than the brute force approach. 
                    while (newSize<=holder.m_id && newSizeMaxArraySize) {
                        newSize=MaxArraySize; 
                    }
                } 
 
                BCLDebug.Trace("SER", "[AddObjectHolder]Reallocating m_objects to have ", newSize, " bins");
                ObjectHolder[] temp = new ObjectHolder[newSize]; 
                Array.Copy(m_objects, temp, m_objects.Length);
                m_objects = temp;
            }
 
            //Find the bin in which we live and make this new element the first element in the bin.
            int index = (int)(holder.m_id & ArrayMask); 
            BCLDebug.Trace("SER", "[AddObjectHolder]Trying to put an object in bin ", index); 

            ObjectHolder tempHolder = m_objects[index]; 
            holder.m_next = tempHolder;
            m_objects[index] = holder;
        }
 
        private bool GetCompletionInfo(FixupHolder fixup, out ObjectHolder holder, out Object member, bool bThrowIfMissing) {
 
            //Set the member id (String or MemberInfo) for the member being fixed up. 
            member = fixup.m_fixupInfo;
 
            //Find the object required for the fixup.  Throw if we can't find it.
            holder = FindObjectHolder(fixup.m_id);
            BCLDebug.Trace("SER", "[ObjectManager.GetCompletionInfo]Getting fixup info for: ", fixup.m_id);
 
            // CompletelyFixed is our poorly named property which indicates if something requires a SerializationInfo fixup
            // or is an incomplete object reference.  We have this particular branch to handle valuetypes which implement 
            // ISerializable.  In that case, we can't do any fixups on them later, so we need to delay the fixups further. 
            if (!holder.CompletelyFixed) {
                if (holder.ObjectValue!=null && holder.ObjectValue is ValueType) { 
                    BCLDebug.Trace("SER", "[ObjectManager.GetCompletionInfo]ValueType implementing ISerializable.  Delaying fixup.");
                    SpecialFixupObjects.Add(holder);
                    return false;
                } 
            }
 
            if (holder==null || holder.CanObjectValueChange || holder.ObjectValue==null) { 
                if (bThrowIfMissing) {
                    BCLDebug.Trace("SER", "[GetCompletionInfo]Unable to find fixup for: ", fixup.m_id); 
                    BCLDebug.Trace("SER", "[GetCompletionInfo]Holder: ", ((holder==null)?"":"Non Null"));
                    BCLDebug.Trace("SER", "[GetCompletionInfo]IsIncomplete: ", (holder.IsIncompleteObjectReference));
                    BCLDebug.Trace("SER", "[GetCompletionInfo]Object: ", ((holder.ObjectValue==null)?"":"Non Null"));
                    if (holder==null) { 
                        throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_NeverSeen"), fixup.m_id));
                    } 
                    if (holder.IsIncompleteObjectReference) { 
                        throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_IORIncomplete"), fixup.m_id));
                    } 
                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ObjectNotSupplied"), fixup.m_id));
                }
                return false;
            } 
            return true;
        } 
 
        private void FixupSpecialObject(ObjectHolder holder) {
            ISurrogateSelector uselessSelector=null; 

            BCLDebug.Assert(holder.RequiresSerInfoFixup,"[ObjectManager.FixupSpecialObject]holder.HasSurrogate||holder.HasISerializable");
            if (holder.HasSurrogate) {
                ISerializationSurrogate surrogate = holder.Surrogate; 
                BCLDebug.Assert(surrogate!=null,"surrogate!=null");
                object returnValue = surrogate.SetObjectData(holder.ObjectValue, holder.SerializationInfo, m_context, uselessSelector); 
                if (returnValue != null) 
                {
                    if (!holder.CanSurrogatedObjectValueChange && returnValue != holder.ObjectValue) 
                        throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_NotCyclicallyReferenceableSurrogate"), surrogate.GetType().FullName));
                    holder.SetObjectValue(returnValue, this);
                }
                holder.m_surrogate = null; 
                holder.SetFlags();
            } else { 
                //Set the object data 
                BCLDebug.Assert(holder.ObjectValue is ISerializable,"holder.m_object is ISerializable");
                BCLDebug.Trace("SER","[ObjectManager.FixupSpecialObject]Fixing up ISerializable object ",holder.ObjectValue," with id ",holder.m_id); 
                CompleteISerializableObject(holder.ObjectValue, holder.SerializationInfo, m_context);
            }
            //Clear anything that we know that we're not going to need.
            holder.SerializationInfo=null; 
            holder.RequiresSerInfoFixup = false;
 
            // For value types, fixups would have been done. So the newly fixed object must be copied 
            // to its container.
            if (holder.RequiresValueTypeFixup && holder.ValueTypeFixupPerformed){ 
                DoValueTypeFixup(null, holder, holder.ObjectValue);
            }
            DoNewlyRegisteredObjectFixups(holder);
        } 

 
        /*============================ResolveObjectReference============================ 
        **Action:Unfortunately, an ObjectReference could actually be a reference to another
        **       object reference and we don't know how far we have to tunnel until we can find the real object.  While 
        **       we're still getting instances of IObjectReference back and we're still getting new objects, keep calling
        **       GetRealObject.  Once we've got the new object, take care of all of the fixups
        **       that we can do now that we've got it.
        ==============================================================================*/ 
        private bool ResolveObjectReference(ObjectHolder holder) {
            Object tempObject; 
            BCLDebug.Assert(holder.IsIncompleteObjectReference,"holder.IsIncompleteObjectReference"); 

            //In the pathological case, an Object implementing IObjectReference could return a reference 
            //to a different object which implements IObjectReference.  This makes us vulnerable to a
            //denial of service attack and stack overflow.  If the depthCount becomes greater than
            //MaxReferenceDepth, we'll throw a SerializationException.
            int depthCount = 0; 

            //We wrap this in a try/catch block to handle the case where we're trying to resolve a chained 
            //list of object reference (e.g. an IObjectReference can't resolve itself without some information 
            //that's currently missing from the graph).  We'll catch the NullReferenceException and come back
            //and try again later.  The downside of this scheme is that if the object actually needed to throw 
            //a NullReferenceException, it's being caught and turned into a SerializationException with a
            //fairly cryptic message.
            try {
                do { 
                    tempObject = holder.ObjectValue;
                    BCLDebug.Trace("SER", "[ResolveObjectReference]ID: ", holder.m_id); 
                    BCLDebug.Trace("SER", "[ResolveObjectReference]HasISerializable: ", holder.HasISerializable); 
                    holder.SetObjectValue(((IObjectReference)(holder.ObjectValue)).GetRealObject(m_context), this);
                    //The object didn't yet have enough information to resolve the reference, so we'll 
                    //return false and the graph walker should call us back again after more objects have
                    //been resolved.
                    //<
 
                    if (holder.ObjectValue==null) {
                        holder.SetObjectValue(tempObject, this); 
                        BCLDebug.Trace("SER", "Object: ", holder.m_id, " did NOT have enough information to resolve the IObjectReference."); 
                        return false;
                    } 
                    if (depthCount++==MaxReferenceDepth) {
                        throw new SerializationException(Environment.GetResourceString("Serialization_TooManyReferences"));
                    }
                } while ((holder.ObjectValue is IObjectReference) && (tempObject!=holder.ObjectValue)); 
            } catch (NullReferenceException) {
                BCLDebug.Trace("SER", "[ResolveObjectReference]Caught exception trying to call GetRealObject."); 
                return false; 
            }
 
            BCLDebug.Trace("SER", "Object: ", holder.m_id, " resolved the IObjectReference.");
            holder.IsIncompleteObjectReference=false;
            DoNewlyRegisteredObjectFixups(holder);
            return true; 
        }
 
 
        /*===============================DoValueTypeFixup===============================
        **Action: 
        **Returns:
        **Arguments:
        ** memberToFix -- the member in the object contained in holder being fixed up.
        ** holder -- the ObjectHolder for the object (a value type in this case) being completed. 
        ** value  -- the data to set into the field.
        **Exceptions: 
        ==============================================================================*/ 
        private bool DoValueTypeFixup(FieldInfo memberToFix, ObjectHolder holder, Object value) {
            TypedReference typedRef; 
            FieldInfo[] fieldsTemp=new FieldInfo[4];
            FieldInfo[] fields=null;
            int   currentFieldIndex=0;
            int[] arrayIndex = null; 
            ValueTypeFixupInfo currFixup=null;
            Object fixupObj=holder.ObjectValue; 
            ObjectHolder originalHolder = holder; 

            BCLDebug.Assert(holder!=null, "[TypedReferenceBuilder.ctor]holder!=null"); 
            BCLDebug.Assert(holder.RequiresValueTypeFixup, "[TypedReferenceBuilder.ctor]holder.RequiresValueTypeFixup");

            //In order to get a TypedReference, we need to get a list of all of the FieldInfos to
            //create the path from our outermost containing object down to the actual field which 
            //we'd like to set.  This loop is used to build up that list.
            while (holder.RequiresValueTypeFixup) { 
                BCLDebug.Trace("SER", "[DoValueTypeFixup] valueType fixsite = ", holder.ObjectValue, " fixobj=",value); 

                //Enlarge the array if required (this is actually fairly unlikely as it would require that we 
                //be nested more than 4 deep.
                if ((currentFieldIndex + 1)>=fieldsTemp.Length) {
                    FieldInfo[] temp = new FieldInfo[fieldsTemp.Length * 2];
                    Array.Copy(fieldsTemp, temp, fieldsTemp.Length); 
                    fieldsTemp = temp;
                } 
 
                //Get the fixup information.  If we have data for our parent field, add it to our list
                //and continue the walk up to find the next outermost containing object.  We cache the 
                //object that we have.  In most cases, we could have just grabbed it after this loop finished.
                //However, if the outermost containing object is an array, we need the object one further
                //down the chain, so we have to do a lot of caching.
                currFixup = holder.ValueFixup; 
                fixupObj = holder.ObjectValue;  //Save the most derived
                if (currFixup.ParentField!=null) { 
                    FieldInfo parentField = currFixup.ParentField; 

                    ObjectHolder tempHolder = FindObjectHolder(currFixup.ContainerID); 
                    if (tempHolder.ObjectValue == null) {
                        break;
                    }
                    if (Nullable.GetUnderlyingType(parentField.FieldType) != null) 
                    {
                        fieldsTemp[currentFieldIndex] = parentField.FieldType.GetField("value", BindingFlags.NonPublic|BindingFlags.Instance); 
                        currentFieldIndex++; 
                    }
 
                    fieldsTemp[currentFieldIndex] = parentField;
                    holder = tempHolder;
                    currentFieldIndex++;
                } else { 
                    //If we find an index into an array, save that information.
                    BCLDebug.Assert(currFixup.ParentIndex!=null, "[ObjectManager.DoValueTypeFixup]currFixup.ParentIndex!=null"); 
                    holder = FindObjectHolder(currFixup.ContainerID); //find the array to fix. 
                    arrayIndex = currFixup.ParentIndex;
                    if (holder.ObjectValue==null) { 
                        break;
                    }
                    break;
                } 
            }
 
            //If the outermost container isn't an array, we need to grab it.  Otherwise, we just need to hang onto 
            //the boxed object that we already grabbed.  We'll assign the boxed object back into the array as the
            //last step. 
            if (!(holder.ObjectValue is Array) && holder.ObjectValue!=null) {
                fixupObj = holder.ObjectValue;
                BCLDebug.Assert(fixupObj!=null, "[ObjectManager.DoValueTypeFixup]FixupObj!=null");
            } 

#if false 
              //We thought that the valuetype had already been placed into it's parent, but when we started 
              //walking the track, we discovered a null, so that's clearly impossible.  At this point, revert
              //to just poking it into the most boxed version that we can. 
              if (fixupObj==null) {
                  fixupObj = originalHolder.ObjectValue;
                  FormatterServices.SerializationSetValue(memberToFix, fixupObj, value);
                  return true; 
              }
#endif 
 
            if (currentFieldIndex!=0) {
 
                //MakeTypedReference requires an array of exactly the correct size that goes from the outermost object
                //in to the innermost field.  We currently have an array of arbitrary size that goes from the innermost
                //object outwards.  We create an array of the right size and do the copy.
                fields = new FieldInfo[currentFieldIndex]; 
                for (int i=0; i0,"temp.m_missingElementsRemaining>0");
                temp.DecrementFixupsRemaining(this);
                if (((temp.DirectlyDependentObjects))==0) { 
                    BCLDebug.Trace("SER", "[DoNewlyRegisteredObjectFixups]Doing fixup for object ", temp.m_id);
                    BCLDebug.Trace("SER", "[DoNewlyRegisteredObjectFixups]ObjectValue ", ((temp.ObjectValue==null)?"":temp.ObjectValue)); 
                    // If this is null, we have the case where a fixup was registered for a child, the object 
                    // required by the fixup was provided, and the object to be fixed hasn't yet been seen.
                    if (temp.ObjectValue!=null) { 
                        CompleteObject(temp, true);
                    } else {
                        temp.MarkForCompletionWhenAvailable();
                    } 
                }
            } 
            BCLDebug.Trace("SER", "[ObjectManager.DoNewlyRegisteredObjectFixups]Exiting."); 
        }
 
        public virtual Object GetObject(long objectID) {
            if (objectID<=0) {
                throw new ArgumentOutOfRangeException("objectID", Environment.GetResourceString("ArgumentOutOfRange_ObjectID"));
            } 

            //Find the bin in which we're interested.  IObjectReference's shouldn't be returned -- the graph 
            //needs to link to the objects to which they refer, not to the references themselves. 
            ObjectHolder holder = FindObjectHolder(objectID);
 
            BCLDebug.Trace("SER", "GetObject. objectID: ", objectID);

            if (holder==null || holder.CanObjectValueChange) {
                BCLDebug.Trace("SER", "GetObject. holder: null or IncompleteObjectReference"); 
                return null;
            } 
 
            BCLDebug.Trace("SER", "GetObject. holder contains: ", ((holder.ObjectValue==null)?"":holder.ObjectValue));
            return holder.ObjectValue; 
        }

       [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
        public virtual void RegisterObject(Object obj, long objectID) { 
            RegisterObject(obj, objectID, null,0,null);
        } 
 

       [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)] 
        public void RegisterObject(Object obj, long objectID, SerializationInfo info) {
            RegisterObject(obj, objectID, info, 0, null);
        }
 

       [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)] 
        public void RegisterObject(Object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member) { 
            RegisterObject(obj, objectID, info, idOfContainingObj, member, null);
        } 


        internal void RegisterString(String obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member)
        { 
            ObjectHolder temp;
            BCLDebug.Assert(member == null || member is FieldInfo, "RegisterString - member is FieldInfo"); 
            BCLDebug.Assert((FindObjectHolder(objectID) == null), "RegisterString - FindObjectHolder(objectID) == null"); 

            temp = new ObjectHolder(obj, objectID, info, null, idOfContainingObj, (FieldInfo)member, null); 
            AddObjectHolder(temp);
            return;
        }
 
       [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
        public void RegisterObject(Object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member, int[] arrayIndex) { 
            ObjectHolder temp; 
            ISerializationSurrogate surrogate = null;
            ISurrogateSelector useless; 

            if (obj==null) {
                throw new ArgumentNullException("obj");
            } 
            if (objectID<=0) {
                throw new ArgumentOutOfRangeException("objectID", Environment.GetResourceString("ArgumentOutOfRange_ObjectID")); 
            } 

            if (member!=null && !(member is RuntimeFieldInfo) && !(member is SerializationFieldInfo)) { 
                throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMemberInfo"));
            }

            if (m_selector != null) 
            {
                Type selectorType=null; 
                if (CanCallGetType(obj)) { 
                    selectorType = obj.GetType();
                } else { 
                    selectorType = typeof(MarshalByRefObject);
                }

                BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]ID: ", objectID, "\tType: ", selectorType, "\tValue: ", obj); 

                //If we need a surrogate for this object, lets find it now. 
                surrogate = m_selector.GetSurrogate(selectorType, m_context, out useless); 
            }
 
            //The object is interested in DeserializationEvents so lets register it.
            if (obj is IDeserializationCallback) {
                DeserializationEventHandler d = new DeserializationEventHandler(((IDeserializationCallback)obj).OnDeserialization);
                AddOnDeserialization(d); 
            }
 
            //Formatter developers may cache and reuse arrayIndex in their code. 
            //So that we don't get bitten by this, take a copy up front.
            if (arrayIndex!=null) { 
              arrayIndex = (int[])arrayIndex.Clone();
            }

            temp = FindObjectHolder(objectID); 
            //This is the first time which we've seen the object, we need to create a new holder.
            if (temp==null) { 
                BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Adding a new object holder for ", objectID, "\tValueType: ", obj.GetType()); 

                temp = new ObjectHolder(obj, objectID, info, surrogate, idOfContainingObj, (FieldInfo)member, arrayIndex); 
                AddObjectHolder(temp);
                if (temp.RequiresDelayedFixup) {
                    SpecialFixupObjects.Add(temp);
                } 
                // We cannot compute whether this has any fixups required or not
                AddOnDeserialized(obj); 
                return; 
            }
 
            //If the object isn't null, we've registered this before.  Not good.
            if (temp.ObjectValue!=null) {
                throw new SerializationException(Environment.GetResourceString("Serialization_RegisterTwice"));
            } 

            //Complete the data in the ObjectHolder 
            temp.UpdateData(obj, info, surrogate, idOfContainingObj, (FieldInfo)member, arrayIndex, this); 

            // The following case will only be true when somebody has registered a fixup on an object before 
            // registering the object itself.  I don't believe that most well-behaved formatters will do this,
            // but we need to allow it anyway.  We will walk the list of fixups which have been recorded on
            // the new object and fix those that we can.  Because the user could still register later fixups
            // on this object, we won't call any implementations of ISerializable now.  If that's required, 
            // it will have to be handled by the code in DoFixups.
            // README README: We have to do the UpdateData before 
            if (temp.DirectlyDependentObjects>0) { 
                CompleteObject(temp, false);
            } 

            if (temp.RequiresDelayedFixup) {
                BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Tracking incomplete objref for element: ", temp.m_id);
                SpecialFixupObjects.Add(temp); 
            }
 
            if (temp.CompletelyFixed) { 
                //Here's where things get tricky.  If this isn't an instance of IObjectReference, we need to walk it's fixup
                //chain and decrement the counters on anything that has reached 0.  Once we've notified all of the dependencies, 
                //we can simply clear the list of dependent objects.
                BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Calling DoNewlyRegisteredObjectFixups for element: ", temp.m_id);
                DoNewlyRegisteredObjectFixups(temp);
                temp.DependentObjects=null; 
            }
 
            //Register the OnDeserialized methods to be invoked after deserialization is complete 
            if (temp.TotalDependentObjects > 0){
                    AddOnDeserialized(obj); 
            }
            else {
                    RaiseOnDeserializedEvent(obj);
            } 

 
            BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Exiting."); 
        }
 
        /*=========================CompleteISerializableObject==========================
        **Action: Completes an object implementing ISerializable.  This will involve calling that
        **        objects constructor which takes an instance of ISerializable and a StreamingContext.
        **Returns: void. 
        **Arguments: Obj     --  The object to be completed.
        **           info    --  The SerializationInfo containing all info for obj. 
        **           context --  The streaming context in which the serialization is taking place. 
        **Exceptions: ArgumentNullException if obj is null
        **            ArgumentException if obj does not implement ISerializable. 
        ==============================================================================*/
        internal void CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context) {
            RuntimeConstructorInfo constInfo = null;
 

            if (obj==null) { 
                throw new ArgumentNullException("obj"); 
            }
 
            if (!(obj is ISerializable)) {
                throw new ArgumentException(Environment.GetResourceString("Serialization_NotISer"));
            }
 
            Type t = obj.GetType();
 
            try { 
#if !FEATURE_PAL
                if (t == TypeOfWindowsIdentity && m_isCrossAppDomain) 
                    constInfo = GetConstructor(t, SIWindowsIdentityConstructorTypes);
                else
#endif
                    constInfo = GetConstructor(t); 
            } catch (Exception e) {
                BCLDebug.Trace("SER", "[CompleteISerializableObject]Unable to get constructor for: ", t); 
                BCLDebug.Trace("SER", "[CompleteISerializableObject]Stack trace was: ", e); 
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ConstructorNotFound"), t), e);
            } 

            constInfo.SerializationInvoke(obj, info, context);
        }
 

        /*================================GetConstructor================================ 
        **Action: 
        **Returns:
        **Arguments: 
        **Exceptions:
        ==============================================================================*/
        internal static RuntimeConstructorInfo GetConstructor(Type t) {
            return GetConstructor(t, SIConstructorTypes); 
        }
 
        internal static RuntimeConstructorInfo GetConstructor(Type t, Type[] ctorParams) { 
            BCLDebug.Assert(t!=null, "[GetConstructor]t!=null");
            BCLDebug.Assert(t is RuntimeType, "[GetConstructor]t is RuntimeType"); 
            RuntimeConstructorInfo ci;

            if ((ci=(RuntimeConstructorInfo)t.Cache[CacheObjType.ConstructorInfo])==null) {
                RuntimeType rt = (RuntimeType)t; 
                ci = rt.GetConstructor(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, 
                    null, CallingConventions.Any, ctorParams, null) as RuntimeConstructorInfo; 
                if (ci==null) {
                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ConstructorNotFound"), t.FullName)); 
                }

                t.Cache[CacheObjType.ConstructorInfo] = ci;
            } 

            return ci; 
        } 

        public virtual void DoFixups() { 
            ObjectHolder temp;
            int fixupCount=-1;

            BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Entering"); 

            //The first thing that we need to do is fixup all of the objects which implement 
            //IObjectReference.  This is complicated by the fact that we need to deal with IReferenceObjects 
            //objects that have a reference to an object implementing IObjectReference.  We continually
            //walk over the list of objects until we've completed all of the object references or until 
            //we can't resolve any more (which may happen if we have two objects implementing IObjectReference
            //which have a circular dependency on each other).  We don't explicitly catch the later case here,
            //it will be caught when we try to do the rest of the fixups and discover that we have some that
            //can't be completed. 
            while (fixupCount!=0) {
                fixupCount=0; 
                //Walk all of the IObjectReferences and ensure that they've been properly completed. 
                ObjectHolderListEnumerator fixupObjectsEnum = SpecialFixupObjects.GetFixupEnumerator();
                while (fixupObjectsEnum.MoveNext()) { 
                    temp = fixupObjectsEnum.Current;
                    if (temp.ObjectValue == null) {
                        BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Object with id: ", temp.m_id, " not found.");
                        throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ObjectNotSupplied"), temp.m_id)); 
                    }
                    BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Looking at object with id: ", temp.m_id, " which has ", 
                                   temp.TotalDependentObjects, " Total Dependent Fixups, but only ", 
                                   (temp.DependentObjects==null)?0:temp.DependentObjects.Count,
                                   " directly dependent objects. Has it been fixed? ", temp.CompletelyFixed); 
                    if (temp.TotalDependentObjects==0) {
                        if (temp.RequiresSerInfoFixup) {
                            FixupSpecialObject(temp);
                            fixupCount++; 
                        } else if (!temp.IsIncompleteObjectReference) {
                            CompleteObject(temp, true); 
                        } 

                        if (temp.IsIncompleteObjectReference && ResolveObjectReference(temp)) { 
                            fixupCount++;
                        }
                    }
                } 
            }
 
            BCLDebug.Assert(m_fixupCount>=0,"[ObjectManager.DoFixups]m_fixupCount>=0"); 

            //If our count is 0, we're done and should just return 
            if (m_fixupCount==0) {
                BCLDebug.Trace("SER", "[ObjectManager.DoFixups]All fixups completed.  We don't need to walk the list.");
                if (TopObject is TypeLoadExceptionHolder)
                    throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_TypeLoadFailure"), ((TypeLoadExceptionHolder)TopObject).TypeName)); 
                return;
            } 
 
            //If our count isn't 0, we had at least one case where an object referenced another object twice.
            //Walk the entire list until the count is 0 or until we find an object which we can't complete. 
            BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Remaining object length is: ", m_objects.Length);
            for (int i=0; i0 /*|| temp.m_missingElements!=null*/) {
                        BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Doing a delayed fixup on object ", temp.m_id); 
                        CompleteObject(temp, true); 
                    }
                    temp = temp.m_next; 
                }
                if (m_fixupCount==0) {
                    return;
                } 
            }
 
            // this assertt can be trigered by user code that manages fixups manually 
            BCLDebug.Correctness(false, "[ObjectManager.DoFixups] Fixup counting is incorrect.");
            throw new SerializationException(Environment.GetResourceString("Serialization_IncorrectNumberOfFixups")); 
        }

        /*================================RegisterFixup=================================
        **Action: Do the actual grunt work of recording a fixup and registering the dependency. 
        **        Create the necessary ObjectHolders and use them to do the addition.
        **Returns: void 
        **Arguments: fixup -- The FixupHolder to be added. 
        **           objectToBeFixed -- The id of the object requiring the fixup.
        **           objectRequired -- The id of the object required to do the fixup. 
        **Exceptions: None.  This is internal-only, so all checking should have been done by this time.
        ==============================================================================*/
        private void RegisterFixup(FixupHolder fixup, long objectToBeFixed, long objectRequired) {
            //Record the fixup with the object that needs it. 
            ObjectHolder ohToBeFixed = FindOrCreateObjectHolder(objectToBeFixed);
            ObjectHolder ohRequired; 
 
            if (ohToBeFixed.RequiresSerInfoFixup && fixup.m_fixupType == FixupHolder.MemberFixup) {
                throw new SerializationException(Environment.GetResourceString("Serialization_InvalidFixupType")); 
            }

            //Add the fixup to the list.
            ohToBeFixed.AddFixup(fixup, this); 

            //Find the object on which we're dependent and 
 
            ohRequired = FindOrCreateObjectHolder(objectRequired);
 
            ohRequired.AddDependency(objectToBeFixed);

            m_fixupCount++;
        } 

        public virtual void RecordFixup(long objectToBeFixed, MemberInfo member, long objectRequired) { 
 
            //Verify our arguments
            if (objectToBeFixed<=0 || objectRequired<=0) { 
                throw new ArgumentOutOfRangeException(((objectToBeFixed<=0)?"objectToBeFixed":"objectRequired"),
                                                      Environment.GetResourceString("Serialization_IdTooSmall"));
            }
 
            if (member==null) {
                throw new ArgumentNullException("member"); 
            } 

            if (!(member is RuntimeFieldInfo) && !(member is SerializationFieldInfo)) { 
                throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_InvalidType"), member.GetType().ToString()));
            }

 
            BCLDebug.Trace("SER", "RecordFixup.  ObjectToBeFixed: ", objectToBeFixed, "\tMember: ", member.Name, "\tRequiredObject: ", objectRequired);
 
            //Create a new fixup holder 
            FixupHolder fixup = new FixupHolder(objectRequired, member, FixupHolder.MemberFixup);
 
            RegisterFixup(fixup, objectToBeFixed, objectRequired);
        }

 
        /*==============================RecordDelayedFixup==============================
        **Action: 
        **Returns: 
        **Arguments:
        **Exceptions: 
        ==============================================================================*/
        public virtual void RecordDelayedFixup(long objectToBeFixed, String memberName, long objectRequired) {
            //Verify our arguments
            if (objectToBeFixed<=0 || objectRequired<=0) { 
                throw new ArgumentOutOfRangeException(((objectToBeFixed<=0)?"objectToBeFixed":"objectRequired"),
                                                      Environment.GetResourceString("Serialization_IdTooSmall")); 
            } 

            if (memberName==null) { 
                throw new ArgumentNullException("memberName");
            }

            BCLDebug.Trace("SER", "RecordDelayedFixup.  ObjectToBeFixed: ", objectToBeFixed, "\tMember: ", memberName, "\tRequiredObject: ", objectRequired); 

            //Create a new fixup holder 
            FixupHolder fixup = new FixupHolder(objectRequired, memberName, FixupHolder.DelayedFixup); 

            RegisterFixup(fixup, objectToBeFixed, objectRequired); 
        }

        /*===========================RecordArrayElementFixup============================
        **Action: 
        **Returns:
        **Arguments: 
        **Exceptions: 
        ==============================================================================*/
        public virtual void RecordArrayElementFixup(long arrayToBeFixed, int index, long objectRequired) { 
            int[] indexArray = new int[1];
            indexArray[0]=index;

            BCLDebug.Trace("SER", "RecordArrayElementFixup.  ObjectToBeFixed: ", arrayToBeFixed, "\tIndex: ", index, "\tRequiredObject: ", objectRequired); 

            RecordArrayElementFixup(arrayToBeFixed, indexArray, objectRequired); 
        } 

        public virtual void RecordArrayElementFixup(long arrayToBeFixed, int[] indices, long objectRequired) { 
            //Verify our arguments
            if (arrayToBeFixed<=0 || objectRequired<=0) {
                throw new ArgumentOutOfRangeException(((arrayToBeFixed<=0)?"objectToBeFixed":"objectRequired"),
                                                      Environment.GetResourceString("Serialization_IdTooSmall")); 
            }
 
            if (indices==null) { 
                throw new ArgumentNullException("indices");
            } 

            BCLDebug.Trace("SER", "RecordArrayElementFixup.  ArrayToBeFixed: ", arrayToBeFixed, "\tRequiredObject: ", objectRequired);
            FixupHolder fixup = new FixupHolder(objectRequired, indices, FixupHolder.ArrayFixup);
            RegisterFixup(fixup, arrayToBeFixed, objectRequired); 
        }
 
 
        /*==========================RaiseDeserializationEvent===========================
        **Action:Raises the deserialization event to any registered object which implements 
        **       IDeserializationCallback.
        **Returns: void
        **Arguments: none
        **Exceptions: None 
        ==============================================================================*/
        public virtual void RaiseDeserializationEvent() { 
            // Invoke OnDerserialized event if applicable 
            if (m_onDeserializedHandler != null) {
                m_onDeserializedHandler(m_context); 
            }

            if (m_onDeserializationHandler!=null) {
                m_onDeserializationHandler(null); 
            }
        } 
 
        internal virtual void AddOnDeserialization(DeserializationEventHandler handler) {
            m_onDeserializationHandler = (DeserializationEventHandler)Delegate.Combine(m_onDeserializationHandler, handler); 
        }

        internal virtual void RemoveOnDeserialization(DeserializationEventHandler handler) {
            m_onDeserializationHandler = (DeserializationEventHandler)Delegate.Remove(m_onDeserializationHandler, handler); 
        }
 
        internal virtual void AddOnDeserialized(Object obj) 
        {
            SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType()); 
            m_onDeserializedHandler = cache.AddOnDeserialized(obj, m_onDeserializedHandler);
        }

        internal virtual void RaiseOnDeserializedEvent(Object obj) 
        {
            SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType()); 
            cache.InvokeOnDeserialized(obj, m_context); 
        }
 
        public void RaiseOnDeserializingEvent(Object obj)
        {
            // Run the OnDeserializing methods
            SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType()); 
            cache.InvokeOnDeserializing(obj, m_context);
        } 
    } 

    internal sealed class ObjectHolder { 
        internal const int INCOMPLETE_OBJECT_REFERENCE = 0x0001;
        internal const int HAS_ISERIALIZABLE           = 0x0002;
        internal const int HAS_SURROGATE               = 0x0004;
        internal const int REQUIRES_VALUETYPE_FIXUP    = 0x0008; 
        internal const int REQUIRES_DELAYED_FIXUP      = HAS_ISERIALIZABLE | HAS_SURROGATE | INCOMPLETE_OBJECT_REFERENCE;
        internal const int SER_INFO_FIXED              = 0x4000; 
        internal const int VALUETYPE_FIXUP_PERFORMED   = 0x8000; 

        private  Object m_object; 
        internal long   m_id;
        private  int    m_missingElementsRemaining;
        private  int    m_missingDecendents;
        internal SerializationInfo m_serInfo; 
        internal ISerializationSurrogate m_surrogate;
        internal FixupHolderList m_missingElements; 
        internal LongList m_dependentObjects; 
        internal ObjectHolder m_next;
        internal int  m_flags; 
        private  bool m_markForFixupWhenAvailable;
        private  ValueTypeFixupInfo m_valueFixup;
        private TypeLoadExceptionHolder m_typeLoad = null;
        private bool m_reachable = false; 

        internal ObjectHolder(long objID) 
            : this(null, objID, null, null, 0, null, null) { 
        }
 
        internal ObjectHolder(Object obj, long objID, SerializationInfo info,
                              ISerializationSurrogate surrogate, long idOfContainingObj, FieldInfo field, int[] arrayIndex) {
            BCLDebug.Assert(objID>=0,"objID>=0");
 
            m_object=obj; //May be null;
            m_id=objID; 
 
            m_flags=0;
            m_missingElementsRemaining=0; 
            m_missingDecendents = 0;
            m_dependentObjects=null;
            m_next=null;
 
            m_serInfo = info;
            m_surrogate = surrogate; 
            m_markForFixupWhenAvailable = false; 

            if (obj is TypeLoadExceptionHolder) 
            {
                m_typeLoad = (TypeLoadExceptionHolder)obj;
            }
 

            if (idOfContainingObj!=0 && ((field!=null && field.FieldType.IsValueType) || arrayIndex!=null)) { 
                if (idOfContainingObj == objID) { 
                    throw new SerializationException(Environment.GetResourceString("Serialization_ParentChildIdentical"));
                } 

                m_valueFixup = new ValueTypeFixupInfo(idOfContainingObj, field, arrayIndex);
            }
 
            SetFlags();
        } 
 
        internal ObjectHolder(String obj, long objID, SerializationInfo info,
                              ISerializationSurrogate surrogate, long idOfContainingObj, FieldInfo field, int[] arrayIndex) { 
            BCLDebug.Assert(objID>=0,"objID>=0");

            m_object=obj; //May be null;
            m_id=objID; 

            m_flags=0; 
            m_missingElementsRemaining=0; 
            m_missingDecendents = 0;
            m_dependentObjects=null; 
            m_next=null;

            m_serInfo = info;
            m_surrogate = surrogate; 
            m_markForFixupWhenAvailable = false;
 
            if (idOfContainingObj!=0 && arrayIndex!=null) { 
                m_valueFixup = new ValueTypeFixupInfo(idOfContainingObj, field, arrayIndex);
            } 

            if (m_valueFixup!=null) {
                m_flags|=REQUIRES_VALUETYPE_FIXUP;
            } 
        }
 
        private void IncrementDescendentFixups(int amount) { 
            m_missingDecendents+=amount;
        } 

        internal void DecrementFixupsRemaining(ObjectManager manager) {
                m_missingElementsRemaining--;
 
                if (RequiresValueTypeFixup) {
                    UpdateDescendentDependencyChain(-1, manager); 
                } 
        }
 
        /*===============================RemoveDependency===============================
        **Action: Removes a dependency of the object represented in this holder.
        **        This is normally the result of the dependency having been filled when
        **        the object is going to be only partially completed.  If we plan to fully 
        **        update the object, we do not take the work to do this.
        **Returns: void. 
        **Arguments: id -- The id of the object for which to remove the dependency. 
        **Exceptions: None, error handling through assertts.
        ==============================================================================*/ 
        internal void RemoveDependency(long id) {
            BCLDebug.Assert(m_dependentObjects!=null, "[ObjectHolder.RemoveDependency]m_dependentObjects!=null");
            BCLDebug.Assert(id>=0, "[ObjectHolder.RemoveDependency]id>=0");
            m_dependentObjects.RemoveElement(id); 
        }
 
        /*===================================AddFixup=================================== 
        **Action: Note a fixup that has to be done before this object can be completed.
        **        Fixups are things that need to happen when other objects in the graph 
        **        are added.  Dependencies are things that need to happen when this object
        **        is added.
        **Returns: void
        **Arguments: fixup -- The fixup holder containing enough information to complete the fixup. 
        **Exceptions: None.
        ==============================================================================*/ 
        internal void AddFixup(FixupHolder fixup, ObjectManager manager) { 
            if (m_missingElements==null) {
                m_missingElements = new FixupHolderList(); 
            }
            m_missingElements.Add(fixup);
            m_missingElementsRemaining++;
 
            if (RequiresValueTypeFixup) {
                UpdateDescendentDependencyChain(1, manager); 
            } 
        }
 
        /*==========================UpdateTotalDependencyChain==========================
        **Action: Updates the total list of dependencies to account for a fixup being added
        **        or completed in a child value class.  This will update all value classes
        **        containing that child and the object which contains all of them. 
        **Returns: void
        **Arguments: amount -- the amount by which to increment (or decrement) the dependency chain. 
        **           manager -- The ObjectManager used to lookup other objects up the chain. 
        **Exceptions: None.  Asserts only.
        ==============================================================================*/ 
        private void UpdateDescendentDependencyChain(int amount, ObjectManager manager) {
            ObjectHolder holder = this;

            //This loop walks one more object up the chain than there are valuetypes.  This 
            //is because we need to increment the TotalFixups in the holders as well.
            do { 
                holder = manager.FindOrCreateObjectHolder(holder.ContainerID); 
                BCLDebug.Trace("SER", "[ObjectManager.UpdateDescendentDependencyChain]Looking for holder with id: ", holder.ContainerID);
                BCLDebug.Assert(holder!=null, "[ObjectHolder.UpdateTotalDependencyChain]holder!=null"); 
                holder.IncrementDescendentFixups(amount);
            } while (holder.RequiresValueTypeFixup);
        }
 
        /*================================AddDependency=================================
        **Action: Note an object which is dependent on the one which will be contained in 
        **        this ObjectHolder.  Dependencies should only be added if the object hasn't 
        **        yet been added.  NB: An incomplete object counts as having no object.
        **Returns: void 
        **Arguments: dependentObject -- the id of the object which is dependent on this object being provided.
        **Exceptions: None.
        ==============================================================================*/
        internal void AddDependency(long dependentObject) { 
            if (m_dependentObjects==null) {
                m_dependentObjects = new LongList(); 
            } 
            m_dependentObjects.Add(dependentObject);
        } 


        /*==================================UpdateData==================================
        **Action: Update the data in the object holder.  This should be called when the object 
        **        is finally registered.  Presumably the ObjectHolder was created to track
        **        some dependencies or preregistered fixups and we now need to actually record the 
        **        object and other associated data.  We take this opportunity to set the flags 
        **        so that we can do some faster processing in the
 



 

 
 
*/
        internal void UpdateData(Object obj, SerializationInfo info, ISerializationSurrogate surrogate, long idOfContainer, FieldInfo field, int[] arrayIndex, ObjectManager manager) { 
            BCLDebug.Assert(obj!=null,"obj!=null");
            BCLDebug.Assert(m_id>0,"m_id>0");

            //Record the fields that we can. 
            SetObjectValue(obj, manager);
            m_serInfo = info; 
            m_surrogate = surrogate; 

            if (idOfContainer!=0 && ((field!=null && field.FieldType.IsValueType) || arrayIndex!=null)) { 
                if (idOfContainer == m_id) {
                    throw new SerializationException(Environment.GetResourceString("Serialization_ParentChildIdentical"));
                }
                m_valueFixup = new ValueTypeFixupInfo(idOfContainer, field, arrayIndex); 
            }
 
            SetFlags(); 

            if (RequiresValueTypeFixup) { 
                UpdateDescendentDependencyChain(m_missingElementsRemaining, manager);
            }
        }
 
        internal void MarkForCompletionWhenAvailable() {
            m_markForFixupWhenAvailable = true; 
        } 

 
        /*===================================SetFlags===================================
        **Action: An internal-only routine to set the flags based upon the data contained in
        **        the ObjectHolder
        **Returns: Void 
        **Arguments: None
        **Exceptions: None 
        ==============================================================================*/ 
        internal void SetFlags() {
            if (m_object is IObjectReference) { 
                m_flags|=INCOMPLETE_OBJECT_REFERENCE;
            }

            m_flags &= ~(HAS_ISERIALIZABLE | HAS_SURROGATE); 
            if (m_surrogate!=null)
                m_flags|=HAS_SURROGATE; 
            else if (m_object is ISerializable) 
                m_flags|=HAS_ISERIALIZABLE;
 
            if (m_valueFixup!=null) {
                m_flags|=REQUIRES_VALUETYPE_FIXUP;
            }
        } 

        internal bool IsIncompleteObjectReference { 
            get { return (m_flags & (INCOMPLETE_OBJECT_REFERENCE /*| HAS_SURROGATE*/)) != 0; } 
            set {
                if (value) { 
                    m_flags|=INCOMPLETE_OBJECT_REFERENCE;
                } else {
                    m_flags&=~INCOMPLETE_OBJECT_REFERENCE;
                } 
            }
        } 
 
        internal bool RequiresDelayedFixup {
            get { return (m_flags & REQUIRES_DELAYED_FIXUP)!=0; } 
        }

        internal bool RequiresValueTypeFixup {
            get { return (m_flags & REQUIRES_VALUETYPE_FIXUP)!=0; } 
        }
 
        // ValueTypes which require fixups are initially handed to the ObjectManager 
        // as boxed objects.  When they're still boxed objects, we should just do fixups
        // on them like we would any other object.  As soon as they're pushed into their 
        // containing object we set ValueTypeFixupPerformed to true and have to go through
        // a more complicated path to set fixed up valuetype objects.
        // We
        internal bool ValueTypeFixupPerformed { 
            get {
                BCLDebug.Trace("SER", "[ObjectManager.ValueTypeFixupPerformed]Flags: ", m_flags & VALUETYPE_FIXUP_PERFORMED); 
                BCLDebug.Trace("SER", "[ObjectManager.ValueTypeFixupPerformed]DependentObjects: ", (m_dependentObjects==null)?"":m_dependentObjects.Count.ToString()); 
                return ( ((m_flags & VALUETYPE_FIXUP_PERFORMED)!=0)||
                        (m_object!=null && ((m_dependentObjects==null) || m_dependentObjects.Count==0))); } 
            set {
                if (value) {
                    m_flags|=VALUETYPE_FIXUP_PERFORMED;
                } 
            }
        } 
 

        internal bool HasISerializable { 
            get {
                return (m_flags & HAS_ISERIALIZABLE)!=0;
            }
        } 

        internal bool HasSurrogate { 
            get { return (m_flags & HAS_SURROGATE)!=0; } 
        }
 
        internal bool CanSurrogatedObjectValueChange
        {
            get
            { 
                return (m_surrogate == null || m_surrogate.GetType() != typeof(SurrogateForCyclicalReference));
            } 
        } 

        internal bool CanObjectValueChange 
        {
            get
            {
                if (IsIncompleteObjectReference) 
                    return true;
                if (HasSurrogate) 
                    return CanSurrogatedObjectValueChange; 
                return false;
            } 
        }


        internal int DirectlyDependentObjects { 
            get {
                return m_missingElementsRemaining; 
            } 
        }
 

        internal int TotalDependentObjects {
            get {
                return m_missingElementsRemaining + m_missingDecendents; 
            }
        } 
 
        internal bool Reachable {
            get { return m_reachable; } 
            set { m_reachable = value; }
        }

        internal bool TypeLoadExceptionReachable { 
            get { return m_typeLoad != null; }
        } 
 
        internal TypeLoadExceptionHolder TypeLoadException {
            get { return m_typeLoad; } 
            set { m_typeLoad = value; }
        }

 
        internal Object ObjectValue {
            get { 
                return m_object; 
            }
        } 

        internal void SetObjectValue(Object obj, ObjectManager manager) {
            m_object = obj;
            if (obj == manager.TopObject) 
                m_reachable = true;
            if (obj is TypeLoadExceptionHolder) 
                m_typeLoad = (TypeLoadExceptionHolder)obj; 

            if (m_markForFixupWhenAvailable) { 
                manager.CompleteObject(this, true);
            }
        }
 
        internal SerializationInfo SerializationInfo {
            get { 
                return m_serInfo; 
            }
 
            set {
                m_serInfo = value;
            }
        } 

        internal ISerializationSurrogate Surrogate { 
            get { 
                return m_surrogate;
            } 
        }

        internal LongList DependentObjects {
            get { 
                return m_dependentObjects;
            } 
            set { 
                m_dependentObjects = value;
            } 
        }

        internal bool RequiresSerInfoFixup {
            get { 
                if (((m_flags & HAS_SURROGATE)==0) && ((m_flags & HAS_ISERIALIZABLE)==0)) {
                    return false; 
                } 

                return (m_flags & SER_INFO_FIXED)==0; 
            }
            set {
                if (!value) {
                    m_flags|=SER_INFO_FIXED; 
                } else {
                    m_flags&=~SER_INFO_FIXED; 
                } 
            }
        } 

        internal ValueTypeFixupInfo ValueFixup {
            get {
                return m_valueFixup; 
            }
        } 
 
        internal bool CompletelyFixed {
            get { 
                return (!RequiresSerInfoFixup && !IsIncompleteObjectReference);
            }
        }
 
        internal long ContainerID {
            get { 
                if (m_valueFixup!=null) { 
                    return m_valueFixup.ContainerID;
                } 
                return 0;
            }
        }
    } 

    [Serializable()] 
    internal class FixupHolder { 
        internal const int ArrayFixup=0x1;
        internal const int MemberFixup=0x2; 
        internal const int DelayedFixup=0x4;

        internal long   m_id;
        internal Object m_fixupInfo; //This is either an array index, a String, or a MemberInfo 
        internal int    m_fixupType;
 
        internal FixupHolder(long id, Object fixupInfo, int fixupType) { 
            BCLDebug.Assert(id>0,"id>0");
            BCLDebug.Assert(fixupInfo!=null,"fixupInfo!=null"); 
            BCLDebug.Assert(fixupType==ArrayFixup || fixupType == MemberFixup || fixupType==DelayedFixup,"fixupType==ArrayFixup || fixupType == MemberFixup || fixupType==DelayedFixup");

            m_id = id;
            m_fixupInfo = fixupInfo; 
            m_fixupType = fixupType;
        } 
    } 

    [Serializable()] 
    internal class FixupHolderList {
        internal const int InitialSize = 2;

        internal FixupHolder[] m_values; 
        internal int m_count;
 
        internal FixupHolderList() : this(InitialSize) { 
        }
 
        internal FixupHolderList(int startingSize) {
            m_count=0;
            m_values = new FixupHolder[startingSize];
        } 

        internal virtual void Add(long id, Object fixupInfo) { 
            if (m_count==m_values.Length) { 
                EnlargeArray();
            } 
            m_values[m_count].m_id=id;
            m_values[m_count++].m_fixupInfo = fixupInfo;
        }
 
        internal virtual void Add(FixupHolder fixup) {
            if (m_count==m_values.Length) { 
                EnlargeArray(); 
            }
            m_values[m_count++]=fixup; 
        }

        private void EnlargeArray() {
            int newLength = m_values.Length*2; 
            if (newLength<0) {
                if (newLength==Int32.MaxValue) { 
                    throw new SerializationException(Environment.GetResourceString("Serialization_TooManyElements")); 
                }
                newLength=Int32.MaxValue; 
            }

            FixupHolder[] temp = new FixupHolder[newLength];
            Array.Copy(m_values, temp, m_count); 
            m_values=temp;
        } 
 

    } 

    [Serializable()]
    internal class LongList {
        private const int InitialSize = 2; 

        private long [] m_values; 
        private int m_count; //The total number of valid items still in the list; 
        private int m_totalItems; //The total number of allocated entries.
                                  //This includes space for items which have been marked as deleted. 
        private int m_currentItem; //Used when doing an enumeration over the list.

        //
        // An m_currentItem of -1 indicates that the enumeration hasn't been started. 
        // An m_values[xx] of -1 indicates that the item has been deleted.
        // 
        internal LongList() : this(InitialSize) { 
        }
 
        internal LongList(int startingSize) {
            m_count=0;
            m_totalItems = 0;
            m_values = new long[startingSize]; 
        }
 
        internal void Add(long value) { 
            if (m_totalItems==m_values.Length) {
                EnlargeArray(); 
            }
            m_values[m_totalItems++]=value;
            m_count++;
        } 

        internal int Count { 
            get { 
                return m_count;
            } 
        }

        internal void StartEnumeration() {
            m_currentItem = -1; 
        }
 
        internal bool MoveNext() { 
            while (++m_currentItem < m_totalItems && m_values[m_currentItem]==-1) {
            } 
            if (m_currentItem==m_totalItems) {
                return false;
            }
            return true; 
        }
 
        internal long Current { 
            get {
                BCLDebug.Assert(m_currentItem!=-1, "[LongList.Current]m_currentItem!=-1"); 
                BCLDebug.Assert(m_values[m_currentItem]!=-1, "[LongList.Current]m_values[m_currentItem]!=-1");
                return m_values[m_currentItem];
            }
        } 

        internal bool RemoveElement(long value) { 
            int i; 
            for (i=0; i0 && startingSize<0x1000,"startingSize>0 && startingSize<0x1000");

            m_count =0;
            m_values = new ObjectHolder[startingSize]; 
        }
 
        internal virtual void Add(ObjectHolder value) { 
            if (m_count==m_values.Length) {
                EnlargeArray(); 
            }
            m_values[m_count++]=value;
        }
 

        internal ObjectHolderListEnumerator GetFixupEnumerator() { 
            return new ObjectHolderListEnumerator(this, true); 
        }
 
        private void EnlargeArray() {
            BCLDebug.Trace("SER", "[ObjectHolderList.EnlargeArray]Enlarging array of size ", m_values.Length);
            int newLength = m_values.Length*2;
            if (newLength<0) { 
                if (newLength==Int32.MaxValue) {
                    throw new SerializationException(Environment.GetResourceString("Serialization_TooManyElements")); 
                } 
                newLength=Int32.MaxValue;
            } 

            ObjectHolder[] temp = new ObjectHolder[newLength];
            Array.Copy(m_values, temp, m_count);
            m_values = temp; 
        }
 
        internal int Version { 
            get {
                return m_count; 
            }
        }

        internal int Count { 
            get {
                return m_count; 
            } 
        }
    } 

    internal class ObjectHolderListEnumerator {
        bool m_isFixupEnumerator;
        ObjectHolderList m_list; 
        int m_startingVersion;
        int m_currPos; 
 
        internal ObjectHolderListEnumerator(ObjectHolderList list, bool isFixupEnumerator) {
            BCLDebug.Assert(list!=null, "[ObjectHolderListEnumerator.ctor]list!=null"); 
            m_list = list;
            m_startingVersion = m_list.Version;
            m_currPos=-1;
            m_isFixupEnumerator = isFixupEnumerator; 
        }
 
        internal bool MoveNext() { 
            BCLDebug.Assert(m_startingVersion==m_list.Version, "[ObjectHolderListEnumerator.MoveNext]m_startingVersion==m_list.Version");
            if (m_isFixupEnumerator) { 
                while (++m_currPos < m_list.Count && m_list.m_values[m_currPos].CompletelyFixed) {
                }
                if (m_currPos==m_list.Count) {
                    return false; 
                }
                return true; 
            } else { 
                m_currPos++;
                if (m_currPos==m_list.Count) { 
                    return false;
                }
                return true;
            } 
        }
 
        internal ObjectHolder Current { 
            get {
                BCLDebug.Assert(m_currPos!=-1, "[ObjectHolderListEnumerator.Current]m_currPos!=-1"); 
                BCLDebug.Assert(m_currPos

                        

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