ObjectManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / Serialization / ObjectManager.cs / 1305376 / 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.Globalization; 
    using System.Diagnostics.Contracts; 

    [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 RuntimeType[] SIConstructorTypes;
#if !FEATURE_PAL
        private static RuntimeType TypeOfWindowsIdentity;
        private static RuntimeType[] 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;
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public ObjectManager(ISurrogateSelector selector, StreamingContext context) : this(selector, context, true, false) { 
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        internal ObjectManager(ISurrogateSelector selector, StreamingContext context, bool checkSecurity, bool isCrossAppDomain) {
            if (checkSecurity) {
                CodeAccessPermission.Demand(PermissionType.SecuritySerialization);
            } 
            m_objects = new ObjectHolder[DefaultInitialSize];
            m_selector = selector; 
            m_context = context; 
            m_isCrossAppDomain = isCrossAppDomain;
        } 


        [System.Security.SecurityCritical]  // auto-generated
        private bool CanCallGetType(Object obj) { 
#if FEATURE_REMOTING
            if (RemotingServices.IsTransparentProxy(obj)) { 
                return false; 
            }
#endif 
            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 RuntimeType[2];
            SIConstructorTypes[0] = (RuntimeType)typeof(SerializationInfo); 
            SIConstructorTypes[1] = (RuntimeType)typeof(StreamingContext); 
#if !FEATURE_PAL && FEATURE_IMPERSONATION
            TypeOfWindowsIdentity = (RuntimeType)typeof(System.Security.Principal.WindowsIdentity); 
            SIWindowsIdentityConstructorTypes = new RuntimeType[1];
            SIWindowsIdentityConstructorTypes[0] = (RuntimeType)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) {
            Contract.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) {
 
            Contract.Assert(holder!=null,"holder!=null");
            BCLDebug.Trace("SER", "[AddObjectHolder]Adding ObjectHolder with id: ", holder.m_id, " Current Bins: ", m_objects.Length); 
            Contract.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(Environment.GetResourceString("Serialization_NeverSeen", fixup.m_id));
                    }
                    if (holder.IsIncompleteObjectReference) {
                        throw new SerializationException(Environment.GetResourceString("Serialization_IORIncomplete", fixup.m_id)); 
                    }
                    throw new SerializationException(Environment.GetResourceString("Serialization_ObjectNotSupplied", fixup.m_id)); 
                } 
                return false;
            } 
            return true;
        }

        [System.Security.SecurityCritical]  // auto-generated 
        private void FixupSpecialObject(ObjectHolder holder) {
            ISurrogateSelector uselessSelector=null; 
 
            Contract.Assert(holder.RequiresSerInfoFixup,"[ObjectManager.FixupSpecialObject]holder.HasSurrogate||holder.HasISerializable");
            if (holder.HasSurrogate) { 
                ISerializationSurrogate surrogate = holder.Surrogate;
                Contract.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 
                Contract.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. 
        ==============================================================================*/
        [System.Security.SecurityCritical]  // auto-generated
        private bool ResolveObjectReference(ObjectHolder holder) {
            Object tempObject; 
            Contract.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: 
        ==============================================================================*/
        [System.Security.SecurityCritical]  // auto-generated 
        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; 
 
            Contract.Assert(holder!=null, "[TypedReferenceBuilder.ctor]holder!=null");
            Contract.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. 
                    Contract.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;
                Contract.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")); 
            }
            Contract.EndContractBlock(); 
 
            //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;
        }
 
        [System.Security.SecurityCritical]  // auto-generated_required
        public virtual void RegisterObject(Object obj, long objectID) { 
            RegisterObject(obj, objectID, null,0,null); 
        }
 

        [System.Security.SecurityCritical]  // auto-generated_required
        public void RegisterObject(Object obj, long objectID, SerializationInfo info) {
            RegisterObject(obj, objectID, info, 0, null); 
        }
 
 
        [System.Security.SecurityCritical]  // auto-generated_required
        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; 
            Contract.Assert(member == null || member is FieldInfo, "RegisterString - member is FieldInfo");
            Contract.Assert((FindObjectHolder(objectID) == null), "RegisterString - FindObjectHolder(objectID) == null"); 

            temp = new ObjectHolder(obj, objectID, info, null, idOfContainingObj, (FieldInfo)member, null);
            AddObjectHolder(temp);
            return; 
        }
 
        [System.Security.SecurityCritical]  // auto-generated_required 
        public void RegisterObject(Object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member, int[] arrayIndex) {
            if (obj==null) { 
                throw new ArgumentNullException("obj");
            }
            if (objectID<=0) {
                throw new ArgumentOutOfRangeException("objectID", Environment.GetResourceString("ArgumentOutOfRange_ObjectID")); 
            }
            Contract.EndContractBlock(); 
 
            if (member!=null && !(member is RuntimeFieldInfo) && !(member is SerializationFieldInfo)) {
                throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMemberInfo")); 
            }

            ObjectHolder temp;
            ISerializationSurrogate surrogate = null; 
            ISurrogateSelector useless;
 
            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);
            }

#if FEATURE_SERIALIZATION 
            //The object is interested in DeserializationEvents so lets register it.
            if (obj is IDeserializationCallback) { 
                DeserializationEventHandler d = new DeserializationEventHandler(((IDeserializationCallback)obj).OnDeserialization); 
                AddOnDeserialization(d);
            } 
#endif

            //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.
        ==============================================================================*/ 
        [System.Security.SecurityCritical]  // auto-generated 
        internal void CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context) {
            if (obj==null) { 
                throw new ArgumentNullException("obj");
            }

            if (!(obj is ISerializable)) { 
                throw new ArgumentException(Environment.GetResourceString("Serialization_NotISer"));
            } 
            Contract.EndContractBlock(); 

            RuntimeConstructorInfo constInfo = null; 

            RuntimeType t = (RuntimeType)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(Environment.GetResourceString("Serialization_ConstructorNotFound", t), e);
            } 
 
            constInfo.SerializationInvoke(obj, info, context);
        } 


        /*================================GetConstructor================================
        **Action: 
        **Returns:
        **Arguments: 
        **Exceptions: 
        ==============================================================================*/
        internal static RuntimeConstructorInfo GetConstructor(RuntimeType t) { 
            return GetConstructor(t, SIConstructorTypes);
        }

        internal static RuntimeConstructorInfo GetConstructor(RuntimeType t, RuntimeType[] ctorParams) { 
            Contract.Assert(t!=null, "[GetConstructor]t!=null");
            Contract.Assert(t is RuntimeType, "[GetConstructor]t is RuntimeType"); 
 
            RuntimeConstructorInfo ci;
            if (!TryGetConstructor(t, ctorParams, out ci)) { 
                throw new SerializationException(Environment.GetResourceString("Serialization_ConstructorNotFound", t.FullName));
            }
            return ci;
        } 

        internal static bool TryGetConstructor(RuntimeType t, out RuntimeConstructorInfo ctorInfo) { 
            return TryGetConstructor(t, SIConstructorTypes, out ctorInfo); 
        }
 
        [SecuritySafeCritical]
        internal static bool TryGetConstructor(RuntimeType t, RuntimeType[] ctorParams, out RuntimeConstructorInfo ctorInfo) {
            Contract.Assert(t != null, "[GetConstructor]t!=null");
            Contract.Assert(t is RuntimeType, "[GetConstructor]t is RuntimeType"); 

            ctorInfo = t.RemotingCache[CacheObjType.ConstructorInfo] as RuntimeConstructorInfo; 
            if (ctorInfo != null) { 
                return true;
            } 

            ctorInfo = t.GetConstructor(
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    null, CallingConventions.Any, ctorParams, null) as RuntimeConstructorInfo; 
            if (ctorInfo != null) {
                t.RemotingCache[CacheObjType.ConstructorInfo] = ctorInfo; 
                return true; 
            }
 
            return false;
        }

        [System.Security.SecuritySafeCritical]  // auto-generated 
        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(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++; 
                        } 
                    }
                } 
            }

            Contract.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(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 assert 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 note the dependency.
            //These dependencies will be processed when the object is supplied.
            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");
            }
            Contract.EndContractBlock(); 

            if (!(member is RuntimeFieldInfo) && !(member is SerializationFieldInfo)) { 
                throw new SerializationException(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"); 
            }
            Contract.EndContractBlock(); 

            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"); 
            } 
            Contract.EndContractBlock();
 
            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) {
            Contract.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) {
            Contract.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 asserts. 
        ==============================================================================*/
        internal void RemoveDependency(long id) { 
            Contract.Assert(m_dependentObjects!=null, "[ObjectHolder.RemoveDependency]m_dependentObjects!=null");
            Contract.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); 
                Contract.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 future. 
        **Returns: void
        **Arguments: obj -- The object being held by this object holder. (This should no longer be null). 
        **           info --The SerializationInfo associated with this object, only required if we're doing delayed fixups.
        **           surrogate -- The surrogate handling this object.  May be null.
        **           idOfContainer -- The id of the object containing this one if this is a valuetype.
        **           member -- the MemberInfo of this object's position in it's container if this is a valuetype. 
        **           manager -- the ObjectManager being used to track these ObjectHolders.
        **Exceptions: None. Asserts only. 
        ==============================================================================*/ 
        [System.Security.SecurityCritical]  // auto-generated
        internal void UpdateData(Object obj, SerializationInfo info, ISerializationSurrogate surrogate, long idOfContainer, FieldInfo field, int[] arrayIndex, ObjectManager manager) { 
            Contract.Assert(obj!=null,"obj!=null");
            Contract.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 check whether or not there are any dependent objects.
        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; 
            }
        } 

        [System.Security.SecurityCritical]  // auto-generated
        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) {
            Contract.Assert(id>0,"id>0"); 
            Contract.Assert(fixupInfo!=null,"fixupInfo!=null");
            Contract.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 { 
                Contract.Assert(m_currentItem!=-1, "[LongList.Current]m_currentItem!=-1");
                Contract.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) { 
            Contract.Assert(list!=null, "[ObjectHolderListEnumerator.ctor]list!=null");
            m_list = list;
            m_startingVersion = m_list.Version;
            m_currPos=-1; 
            m_isFixupEnumerator = isFixupEnumerator;
        } 
 
        internal bool MoveNext() {
            Contract.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 { 
                Contract.Assert(m_currPos!=-1, "[ObjectHolderListEnumerator.Current]m_currPos!=-1");
                Contract.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