The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization \ ObjectHolderListEnumerator

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class: ObjectManager
  18. **
  19. **
  20. ** Purpose:
  21. **
  22. **
  23. ============================================================*/
  24. namespace System.Runtime.Serialization
  25. {
  26.     using System;
  27.     using System.Collections;
  28.     using System.Collections.Generic;
  29.     using System.Diagnostics;
  30.     using System.Reflection;
  31.     using System.Reflection.Cache;
  32.     using System.Runtime.Remoting;
  33.     using System.Security.Permissions;
  34.     using System.Security;
  35.     using System.Runtime.Remoting.Messaging;
  36.     using System.Globalization;
  37.    
  38.     [System.Runtime.InteropServices.ComVisible(true)]
  39.     public class ObjectManager
  40.     {
  41.         private const int DefaultInitialSize = 16;
  42.         private const int MaxArraySize = 4096;
  43.         //MUST BE A POWER OF 2!
  44.         private const int ArrayMask = MaxArraySize - 1;
  45.         private const int MaxReferenceDepth = 100;
  46.        
  47.         private DeserializationEventHandler m_onDeserializationHandler;
  48.         private SerializationEventHandler m_onDeserializedHandler;
  49.        
  50.         private static Type[] SIConstructorTypes;
  51.         internal ObjectHolder[] m_objects;
  52.         internal object m_topObject = null;
  53.         internal ObjectHolderList m_specialFixupObjects;
  54.         //This is IObjectReference, ISerializable, or has a Surrogate.
  55.         internal long m_fixupCount;
  56.         internal ISurrogateSelector m_selector;
  57.         internal StreamingContext m_context;
  58.         bool m_isCrossAppDomain;
  59.        
  60.         public ObjectManager(ISurrogateSelector selector, StreamingContext context) : this(selector, context, true, false)
  61.         {
  62.         }
  63.        
  64.         internal ObjectManager(ISurrogateSelector selector, StreamingContext context, bool checkSecurity, bool isCrossAppDomain)
  65.         {
  66.             if (checkSecurity) {
  67.                 CodeAccessPermission.DemandInternal(PermissionType.SecuritySerialization);
  68.             }
  69.             m_objects = new ObjectHolder[DefaultInitialSize];
  70.             m_selector = selector;
  71.             m_context = context;
  72.             m_isCrossAppDomain = isCrossAppDomain;
  73.         }
  74.        
  75.        
  76.         private bool CanCallGetType(object obj)
  77.         {
  78.             if (RemotingServices.IsTransparentProxy(obj)) {
  79.                 return false;
  80.             }
  81.             return true;
  82.         }
  83.        
  84.         internal object TopObject {
  85.             get { return m_topObject; }
  86.             set { m_topObject = value; }
  87.         }
  88.        
  89.         internal ObjectHolderList SpecialFixupObjects {
  90.             get {
  91.                 if (m_specialFixupObjects == null) {
  92.                     m_specialFixupObjects = new ObjectHolderList();
  93.                 }
  94.                 return m_specialFixupObjects;
  95.             }
  96.         }
  97.        
  98.         static ObjectManager()
  99.         {
  100.             SIConstructorTypes = new Type[2];
  101.             SIConstructorTypes[0] = typeof(SerializationInfo);
  102.             SIConstructorTypes[1] = typeof(StreamingContext);
  103.         }
  104.        
  105. /*==================================FindObject==================================
  106.         **Action: An internal-only function to find the object with id <CODE>objectID</CODE>.
  107.         **This function does no error checking, it assumes that all of that has been done already.
  108.         **Returns: The ObjectHolder for <CODE>objectID</CODE> or null if it doesn't exist.
  109.         **Arguments: objectID -- The objectID of the Object for which we're searching.
  110.         **Exceptions: None.  This is internal only. 
  111.         **Callers should verify that objectID is greater than 0.
  112.         ==============================================================================*/       
  113.         internal ObjectHolder FindObjectHolder(long objectID)
  114.         {
  115.             BCLDebug.Assert(objectID > 0, "objectID>0");
  116.            
  117.             //The index of the bin in which we live is rightmost n bits of the objectID.
  118.             int index = (int)(objectID & ArrayMask);
  119.             if (index >= m_objects.Length) {
  120.                 return null;
  121.             }
  122.            
  123.             //Find the bin in which we live.
  124.             ObjectHolder temp = m_objects[index];
  125.            
  126.             //Walk the chain in that bin. Return the ObjectHolder if we find it, otherwise
  127.             //return null.
  128.             while (temp != null) {
  129.                 if (temp.m_id == objectID) {
  130.                     return temp;
  131.                 }
  132.                 temp = temp.m_next;
  133.             }
  134.             return temp;
  135.         }
  136.        
  137.        
  138.         internal ObjectHolder FindOrCreateObjectHolder(long objectID)
  139.         {
  140.             ObjectHolder holder;
  141.             holder = FindObjectHolder(objectID);
  142.             if (holder == null) {
  143.                 holder = new ObjectHolder(objectID);
  144.                 AddObjectHolder(holder);
  145.             }
  146.             return holder;
  147.         }
  148.        
  149.        
  150. /*===============================AddObjectHolder================================
  151.         **Action: Add the provided ObjectHolder to collection of ObjectHolders.
  152.         **        Enlarges the collection as appropriate.
  153.         **Returns: void
  154.         **Arguments: holder The ObjectHolder to be added.
  155.         **Exceptions: Internal only.  Caller should verify that <CODE>holder</CODE> is
  156.         **            not null.
  157.         ==============================================================================*/       
  158.         private void AddObjectHolder(ObjectHolder holder)
  159.         {
  160.            
  161.             BCLDebug.Assert(holder != null, "holder!=null");
  162.             BCLDebug.Trace("SER", "[AddObjectHolder]Adding ObjectHolder with id: ", holder.m_id, " Current Bins: ", m_objects.Length);
  163.             BCLDebug.Assert(holder.m_id >= 0, "holder.m_id>=0");
  164.            
  165.             //If the id that we need to place is greater than our current length, and less
  166.             //than the maximum allowable size of the array. We need to double the size
  167.             //of the array. If the array has already reached it's maximum allowable size,
  168.             //we chain elements off of the buckets.
  169.             if (holder.m_id >= m_objects.Length && m_objects.Length != MaxArraySize) {
  170.                 int newSize = MaxArraySize;
  171.                
  172.                 if (holder.m_id < (MaxArraySize / 2)) {
  173.                     newSize = (m_objects.Length * 2);
  174.                    
  175.                     //Keep doubling until we're larger than our target size.
  176.                     //We could also do this with log operations, but that would
  177.                     //be slower than the brute force approach.
  178.                     while (newSize <= holder.m_id && newSize < MaxArraySize) {
  179.                         newSize *= 2;
  180.                     }
  181.                    
  182.                     if (newSize > MaxArraySize) {
  183.                         newSize = MaxArraySize;
  184.                     }
  185.                 }
  186.                
  187.                 BCLDebug.Trace("SER", "[AddObjectHolder]Reallocating m_objects to have ", newSize, " bins");
  188.                 ObjectHolder[] temp = new ObjectHolder[newSize];
  189.                 Array.Copy(m_objects, temp, m_objects.Length);
  190.                 m_objects = temp;
  191.             }
  192.            
  193.             //Find the bin in which we live and make this new element the first element in the bin.
  194.             int index = (int)(holder.m_id & ArrayMask);
  195.             BCLDebug.Trace("SER", "[AddObjectHolder]Trying to put an object in bin ", index);
  196.            
  197.             ObjectHolder tempHolder = m_objects[index];
  198.             holder.m_next = tempHolder;
  199.             m_objects[index] = holder;
  200.         }
  201.        
  202.         private bool GetCompletionInfo(FixupHolder fixup, out ObjectHolder holder, out object member, bool bThrowIfMissing)
  203.         {
  204.            
  205.             //Set the member id (String or MemberInfo) for the member being fixed up.
  206.             member = fixup.m_fixupInfo;
  207.            
  208.             //Find the object required for the fixup. Throw if we can't find it.
  209.             holder = FindObjectHolder(fixup.m_id);
  210.             BCLDebug.Trace("SER", "[ObjectManager.GetCompletionInfo]Getting fixup info for: ", fixup.m_id);
  211.            
  212.             // CompletelyFixed is our poorly named property which indicates if something requires a SerializationInfo fixup
  213.             // or is an incomplete object reference. We have this particular branch to handle valuetypes which implement
  214.             // ISerializable. In that case, we can't do any fixups on them later, so we need to delay the fixups further.
  215.             if (!holder.CompletelyFixed) {
  216.                 if (holder.ObjectValue != null && holder.ObjectValue is ValueType) {
  217.                     BCLDebug.Trace("SER", "[ObjectManager.GetCompletionInfo]ValueType implementing ISerializable. Delaying fixup.");
  218.                     SpecialFixupObjects.Add(holder);
  219.                     return false;
  220.                 }
  221.             }
  222.            
  223.             if (holder == null || holder.IsIncompleteObjectReference || holder.HasSurrogate || holder.ObjectValue == null) {
  224.                 if (bThrowIfMissing) {
  225.                     BCLDebug.Trace("SER", "[GetCompletionInfo]Unable to find fixup for: ", fixup.m_id);
  226.                     BCLDebug.Trace("SER", "[GetCompletionInfo]Holder: ", ((holder == null) ? "<null>" : "Non Null"));
  227.                     BCLDebug.Trace("SER", "[GetCompletionInfo]IsIncomplete: ", (holder.IsIncompleteObjectReference));
  228.                     BCLDebug.Trace("SER", "[GetCompletionInfo]Object: ", ((holder.ObjectValue == null) ? "<null>" : "Non Null"));
  229.                     if (holder == null) {
  230.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_NeverSeen"), fixup.m_id));
  231.                     }
  232.                     if (holder.IsIncompleteObjectReference) {
  233.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_IORIncomplete"), fixup.m_id));
  234.                     }
  235.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ObjectNotSupplied"), fixup.m_id));
  236.                 }
  237.                 return false;
  238.             }
  239.             return true;
  240.         }
  241.        
  242.         private void FixupSpecialObject(ObjectHolder holder)
  243.         {
  244.             ISurrogateSelector uselessSelector = null;
  245.            
  246.             BCLDebug.Assert(holder.RequiresSerInfoFixup, "[ObjectManager.FixupSpecialObject]holder.HasSurrogate||holder.HasISerializable");
  247.             if (holder.HasSurrogate) {
  248.                 ISerializationSurrogate surrogate = holder.Surrogate;
  249.                 BCLDebug.Assert(surrogate != null, "surrogate!=null");
  250.                 object returnValue = surrogate.SetObjectData(holder.ObjectValue, holder.SerializationInfo, m_context, uselessSelector);
  251.                 if (returnValue != null)
  252.                     holder.SetObjectValue(returnValue, this);
  253.                 holder.m_surrogate = null;
  254.                 holder.SetFlags();
  255.             }
  256.             else {
  257.                 //Set the object data
  258.                 BCLDebug.Assert(holder.ObjectValue is ISerializable, "holder.m_object is ISerializable");
  259.                 BCLDebug.Trace("SER", "[ObjectManager.FixupSpecialObject]Fixing up ISerializable object ", holder.ObjectValue, " with id ", holder.m_id);
  260.                 CompleteISerializableObject(holder.ObjectValue, holder.SerializationInfo, m_context);
  261.             }
  262.             //Clear anything that we know that we're not going to need.
  263.             holder.SerializationInfo = null;
  264.             holder.RequiresSerInfoFixup = false;
  265.            
  266.             // For value types, fixups would have been done. So the newly fixed object must be copied
  267.             // to its container.
  268.             if (holder.RequiresValueTypeFixup && holder.ValueTypeFixupPerformed) {
  269.                 DoValueTypeFixup(null, holder, holder.ObjectValue);
  270.             }
  271.             DoNewlyRegisteredObjectFixups(holder);
  272.         }
  273.        
  274.        
  275. /*============================ResolveObjectReference============================
  276.         **Action:Unfortunately, an ObjectReference could actually be a reference to another
  277.         **      object reference and we don't know how far we have to tunnel until we can find the real object.  While
  278.         **      we're still getting instances of IObjectReference back and we're still getting new objects, keep calling
  279.         **      GetRealObject.  Once we've got the new object, take care of all of the fixups
  280.         **      that we can do now that we've got it.
  281.         ==============================================================================*/       
  282.         private bool ResolveObjectReference(ObjectHolder holder)
  283.         {
  284.             object tempObject;
  285.             BCLDebug.Assert(holder.IsIncompleteObjectReference, "holder.IsIncompleteObjectReference");
  286.            
  287.             //In the pathological case, an Object implementing IObjectReference could return a reference
  288.             //to a different object which implements IObjectReference. This makes us vulnerable to a
  289.             //denial of service attack and stack overflow. If the depthCount becomes greater than
  290.             //MaxReferenceDepth, we'll throw a SerializationException.
  291.             int depthCount = 0;
  292.            
  293.             //We wrap this in a try/catch block to handle the case where we're trying to resolve a chained
  294.             //list of object reference (e.g. an IObjectReference can't resolve itself without some information
  295.             //that's currently missing from the graph). We'll catch the NullReferenceException and come back
  296.             //and try again later. The downside of this scheme is that if the object actually needed to throw
  297.             //a NullReferenceException, it's being caught and turned into a SerializationException with a
  298.             //fairly cryptic message.
  299.             try {
  300.                 do {
  301.                     tempObject = holder.ObjectValue;
  302.                     BCLDebug.Trace("SER", "[ResolveObjectReference]ID: ", holder.m_id);
  303.                     BCLDebug.Trace("SER", "[ResolveObjectReference]HasISerializable: ", holder.HasISerializable);
  304.                     holder.SetObjectValue(((IObjectReference)(holder.ObjectValue)).GetRealObject(m_context), this);
  305.                     //The object didn't yet have enough information to resolve the reference, so we'll
  306.                     //return false and the graph walker should call us back again after more objects have
  307.                     //been resolved.
  308.                     if (holder.ObjectValue == null) {
  309.                         holder.SetObjectValue(tempObject, this);
  310.                         BCLDebug.Trace("SER", "Object: ", holder.m_id, " did NOT have enough information to resolve the IObjectReference.");
  311.                         return false;
  312.                     }
  313.                     if (depthCount++ == MaxReferenceDepth) {
  314.                         throw new SerializationException(Environment.GetResourceString("Serialization_TooManyReferences"));
  315.                     }
  316.                 }
  317.                 while ((holder.ObjectValue is IObjectReference) && (tempObject != holder.ObjectValue));
  318.             }
  319.             catch (NullReferenceException) {
  320.                 BCLDebug.Trace("SER", "[ResolveObjectReference]Caught exception trying to call GetRealObject.");
  321.                 return false;
  322.             }
  323.            
  324.             BCLDebug.Trace("SER", "Object: ", holder.m_id, " resolved the IObjectReference.");
  325.             holder.IsIncompleteObjectReference = false;
  326.             DoNewlyRegisteredObjectFixups(holder);
  327.             return true;
  328.         }
  329.        
  330.        
  331. /*===============================DoValueTypeFixup===============================
  332.         **Action:
  333.         **Returns:
  334.         **Arguments:
  335.         ** memberToFix -- the member in the object contained in holder being fixed up.
  336.         ** holder -- the ObjectHolder for the object (a value type in this case) being completed.
  337.         ** value  -- the data to set into the field.
  338.         **Exceptions:
  339.         ==============================================================================*/       
  340.         private bool DoValueTypeFixup(FieldInfo memberToFix, ObjectHolder holder, object value)
  341.         {
  342.             TypedReference typedRef;
  343.             FieldInfo[] fieldsTemp = new FieldInfo[4];
  344.             FieldInfo[] fields = null;
  345.             int currentFieldIndex = 0;
  346.             int[] arrayIndex = null;
  347.             ValueTypeFixupInfo currFixup = null;
  348.             object fixupObj = holder.ObjectValue;
  349.             ObjectHolder originalHolder = holder;
  350.            
  351.             BCLDebug.Assert(holder != null, "[TypedReferenceBuilder.ctor]holder!=null");
  352.             BCLDebug.Assert(holder.RequiresValueTypeFixup, "[TypedReferenceBuilder.ctor]holder.RequiresValueTypeFixup");
  353.            
  354.             //In order to get a TypedReference, we need to get a list of all of the FieldInfos to
  355.             //create the path from our outermost containing object down to the actual field which
  356.             //we'd like to set. This loop is used to build up that list.
  357.             while (holder.RequiresValueTypeFixup) {
  358.                 BCLDebug.Trace("SER", "[DoValueTypeFixup] valueType fixsite = ", holder.ObjectValue, " fixobj=", value);
  359.                
  360.                 //Enlarge the array if required (this is actually fairly unlikely as it would require that we
  361.                 //be nested more than 4 deep.
  362.                 if ((currentFieldIndex + 1) >= fieldsTemp.Length) {
  363.                     FieldInfo[] temp = new FieldInfo[fieldsTemp.Length * 2];
  364.                     Array.Copy(fieldsTemp, temp, fieldsTemp.Length);
  365.                     fieldsTemp = temp;
  366.                 }
  367.                
  368.                 //Get the fixup information. If we have data for our parent field, add it to our list
  369.                 //and continue the walk up to find the next outermost containing object. We cache the
  370.                 //object that we have. In most cases, we could have just grabbed it after this loop finished.
  371.                 //However, if the outermost containing object is an array, we need the object one further
  372.                 //down the chain, so we have to do a lot of caching.
  373.                 currFixup = holder.ValueFixup;
  374.                 fixupObj = holder.ObjectValue;
  375.                 //Save the most derived
  376.                 if (currFixup.ParentField != null) {
  377.                     FieldInfo parentField = currFixup.ParentField;
  378.                    
  379.                     ObjectHolder tempHolder = FindObjectHolder(currFixup.ContainerID);
  380.                     if (tempHolder.ObjectValue == null) {
  381.                         break;
  382.                     }
  383.                     if (Nullable.GetUnderlyingType(parentField.FieldType) != null) {
  384.                         fieldsTemp[currentFieldIndex] = parentField.FieldType.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance);
  385.                         currentFieldIndex++;
  386.                     }
  387.                    
  388.                     fieldsTemp[currentFieldIndex] = parentField;
  389.                     holder = tempHolder;
  390.                     currentFieldIndex++;
  391.                 }
  392.                 else {
  393.                     //If we find an index into an array, save that information.
  394.                     BCLDebug.Assert(currFixup.ParentIndex != null, "[ObjectManager.DoValueTypeFixup]currFixup.ParentIndex!=null");
  395.                     holder = FindObjectHolder(currFixup.ContainerID);
  396.                     //find the array to fix.
  397.                     arrayIndex = currFixup.ParentIndex;
  398.                     if (holder.ObjectValue == null) {
  399.                         break;
  400.                     }
  401.                     break;
  402.                 }
  403.             }
  404.            
  405.             //If the outermost container isn't an array, we need to grab it. Otherwise, we just need to hang onto
  406.             //the boxed object that we already grabbed. We'll assign the boxed object back into the array as the
  407.             //last step.
  408.             if (!(holder.ObjectValue is Array) && holder.ObjectValue != null) {
  409.                 fixupObj = holder.ObjectValue;
  410.                 BCLDebug.Assert(fixupObj != null, "[ObjectManager.DoValueTypeFixup]FixupObj!=null");
  411.             }
  412.            
  413.            
  414.             if (currentFieldIndex != 0) {
  415.                
  416.                 //MakeTypedReference requires an array of exactly the correct size that goes from the outermost object
  417.                 //in to the innermost field. We currently have an array of arbitrary size that goes from the innermost
  418.                 //object outwards. We create an array of the right size and do the copy.
  419.                 fields = new FieldInfo[currentFieldIndex];
  420.                 for (int i = 0; i < currentFieldIndex; i++) {
  421.                     FieldInfo fieldInfo = fieldsTemp[(currentFieldIndex - 1 - i)];
  422.                     SerializationFieldInfo serInfo = fieldInfo as SerializationFieldInfo;
  423.                     fields[i] = serInfo == null ? fieldInfo : serInfo.FieldInfo;
  424.                 }
  425.                
  426.                 BCLDebug.Assert(fixupObj != null, "[ObjectManager.DoValueTypeFixup]fixupObj!=null");
  427.                 DumpValueTypeFixup(fixupObj, fields, memberToFix, value);
  428.                 //Make the TypedReference and use it to set the value.
  429.                 typedRef = TypedReference.MakeTypedReference(fixupObj, fields);
  430.                 if (memberToFix != null)
  431.                     ((RuntimeFieldInfo)memberToFix).SetValueDirect(typedRef, value);
  432.                 else
  433.                     //((RuntimeFieldInfo)memberToFix).SetValueDirectImpl(value, false, typedRef);
  434.                     TypedReference.SetTypedReference(typedRef, value);
  435.             }
  436.             else if (memberToFix != null) {
  437.                 DumpValueTypeFixup(fixupObj, null, memberToFix, value);
  438.                 FormatterServices.SerializationSetValue(memberToFix, fixupObj, value);
  439.             }
  440.            
  441.             //If we have an array index, it means that our outermost container was an array. We don't have
  442.             //any way to build a TypedReference into an array, so we'll use the array functions to set the value.
  443.             if (arrayIndex != null && holder.ObjectValue != null) {
  444.                 ((Array)(holder.ObjectValue)).SetValue(fixupObj, arrayIndex);
  445.             }
  446.            
  447.             return true;
  448.         }
  449.        
  450.        
  451.        
  452.        
  453.         [Conditional("SER_LOGGING")]
  454.         void DumpValueTypeFixup(object obj, FieldInfo[] intermediateFields, FieldInfo memberToFix, object value)
  455.         {
  456.             System.Text.StringBuilder sb = new System.Text.StringBuilder(" " + obj);
  457.             if (intermediateFields != null)
  458.                 for (int i = 0; i < intermediateFields.Length; i++) {
  459.                     sb.Append("." + intermediateFields[i].Name);
  460.                 }
  461.             sb.Append("." + memberToFix.Name + "=" + value);
  462.             BCLDebug.Trace("SER", sb.ToString());
  463.         }
  464.        
  465.        
  466. /*================================CompleteObject================================
  467.         **Action:
  468.         **Returns:
  469.         **Arguments:
  470.         **Exceptions:
  471.         ==============================================================================*/       
  472.         internal void CompleteObject(ObjectHolder holder, bool bObjectFullyComplete)
  473.         {
  474.             FixupHolderList fixups = holder.m_missingElements;
  475.             FixupHolder currentFixup;
  476.             SerializationInfo si;
  477.             object fixupInfo = null;
  478.             ObjectHolder tempObjectHolder = null;
  479.             int fixupsPerformed = 0;
  480.            
  481.             BCLDebug.Assert(holder != null, "[ObjectManager.CompleteObject]holder.m_object!=null");
  482.             if (holder.ObjectValue == null) {
  483.                 throw new SerializationException(Environment.GetResourceString("Serialization_MissingObject", holder.m_id));
  484.             }
  485.            
  486.             if (fixups == null) {
  487.                 return;
  488.             }
  489.             //If either one of these conditions is true, we need to update the data in the
  490.             //SerializationInfo before calling SetObjectData.
  491.             if (holder.HasSurrogate || holder.HasISerializable) {
  492.                 si = holder.m_serInfo;
  493.                
  494.                 if (si == null) {
  495.                     throw new SerializationException(Environment.GetResourceString("Serialization_InvalidFixupDiscovered"));
  496.                 }
  497.                
  498.                 BCLDebug.Trace("SER", "[ObjectManager.CompleteObject]Complete object ", holder.m_id, " of SI Type: ", si.FullTypeName);
  499.                 //Walk each of the fixups and complete the name-value pair in the SerializationInfo.
  500.                 if (fixups != null) {
  501.                     for (int i = 0; i < fixups.m_count; i++) {
  502.                         if (fixups.m_values[i] == null) {
  503.                             continue;
  504.                         }
  505.                         BCLDebug.Assert(fixups.m_values[i].m_fixupType == FixupHolder.DelayedFixup, "fixups.m_values[i].m_fixupType==FixupHolder.DelayedFixup");
  506.                         if (GetCompletionInfo(fixups.m_values[i], out tempObjectHolder, out fixupInfo, bObjectFullyComplete)) {
  507.                             //Walk the SerializationInfo and find the member needing completion. All we have to do
  508.                             //at this point is set the member into the Object
  509.                             BCLDebug.Trace("SER", "[ObjectManager.CompleteObject]Updating object ", holder.m_id, " with object ", tempObjectHolder.m_id);
  510.                             object holderValue = tempObjectHolder.ObjectValue;
  511.                             if (CanCallGetType(holderValue)) {
  512.                                 si.UpdateValue((string)fixupInfo, holderValue, holderValue.GetType());
  513.                             }
  514.                             else {
  515.                                 si.UpdateValue((string)fixupInfo, holderValue, typeof(MarshalByRefObject));
  516.                             }
  517.                             //Decrement our total number of fixups left to do.
  518.                             fixupsPerformed++;
  519.                             fixups.m_values[i] = null;
  520.                             if (!bObjectFullyComplete) {
  521.                                 holder.DecrementFixupsRemaining(this);
  522.                                 tempObjectHolder.RemoveDependency(holder.m_id);
  523.                             }
  524.                         }
  525.                     }
  526.                 }
  527.                
  528.             }
  529.             else {
  530.                 BCLDebug.Trace("SER", "[ObjectManager.CompleteObject]Non-ISerializableObject: ", holder.m_id);
  531.                 for (int i = 0; i < fixups.m_count; i++) {
  532.                     currentFixup = fixups.m_values[i];
  533.                     if (currentFixup == null) {
  534.                         continue;
  535.                     }
  536.                     BCLDebug.Trace("SER", "[ObjectManager.CompleteObject]Getting fixup info for object: ", currentFixup.m_id);
  537.                     if (GetCompletionInfo(currentFixup, out tempObjectHolder, out fixupInfo, bObjectFullyComplete)) {
  538.                         BCLDebug.Trace("SER", "[ObjectManager.CompleteObject]Fixing up: ", currentFixup.m_id);
  539.                        
  540.                         // Check to make sure we are not both reachable from the topObject
  541.                         // and there was a typeloadexception
  542.                         if (tempObjectHolder.TypeLoadExceptionReachable) {
  543.                             holder.TypeLoadException = tempObjectHolder.TypeLoadException;
  544.                             // If the holder is both reachable and typeloadexceptionreachable
  545.                             // throw an exception with the type name
  546.                             if (holder.Reachable) {
  547.                                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_TypeLoadFailure"), holder.TypeLoadException.TypeName));
  548.                             }
  549.                         }
  550.                        
  551.                         // If the current holder is reachable, mark the dependant reachable as well
  552.                         if (holder.Reachable)
  553.                             tempObjectHolder.Reachable = true;
  554.                        
  555.                        
  556.                         //There are two types of fixups that we could be doing: array or member.
  557.                         //Delayed Fixups should be handled by the above branch.
  558.                         switch (currentFixup.m_fixupType) {
  559.                             case FixupHolder.ArrayFixup:
  560.                                 BCLDebug.Assert(holder.ObjectValue is Array, "holder.ObjectValue is Array");
  561.                                 if (holder.RequiresValueTypeFixup) {
  562.                                     throw new SerializationException(Environment.GetResourceString("Serialization_ValueTypeFixup"));
  563.                                 }
  564.                                 else {
  565.                                     ((Array)(holder.ObjectValue)).SetValue(tempObjectHolder.ObjectValue, ((int[])fixupInfo));
  566.                                 }
  567.                                 break;
  568.                             case FixupHolder.MemberFixup:
  569.                                 BCLDebug.Assert(fixupInfo is MemberInfo, "fixupInfo is MemberInfo");
  570.                                 //Fixup the member directly.
  571.                                 MemberInfo tempMember = (MemberInfo)fixupInfo;
  572.                                 if (tempMember.MemberType == MemberTypes.Field) {
  573.                                     BCLDebug.Trace("SER", "[ObjectManager.CompleteObject]Fixing member: ", tempMember.Name, " in object ", holder.m_id, " with object ", tempObjectHolder.m_id);
  574.                                    
  575.                                     // If we have a valuetype that's been boxed to an object and requires a fixup,
  576.                                     // there are two possible states:
  577.                                     // (a)The valuetype has never been fixed up into it's container. In this case, we should
  578.                                     // just fix up the boxed valuetype. The task of pushing that valuetype into it's container
  579.                                     // will be handled later. This case is handled by the else clause of the following statement.
  580.                                     // (b)The valuetype has already been inserted into it's container. In that case, we need
  581.                                     // to go through the more complicated path laid out in DoValueTypeFixup. We can tell that the
  582.                                     // valuetype has already been inserted into it's container because we set ValueTypeFixupPerformed
  583.                                     // to true when we do this.
  584.                                     if (holder.RequiresValueTypeFixup && holder.ValueTypeFixupPerformed) {
  585.                                         if (!DoValueTypeFixup((FieldInfo)tempMember, holder, tempObjectHolder.ObjectValue)) {
  586.                                             throw new SerializationException(Environment.GetResourceString("Serialization_PartialValueTypeFixup"));
  587.                                         }
  588.                                     }
  589.                                     else {
  590.                                         FormatterServices.SerializationSetValue(tempMember, holder.ObjectValue, tempObjectHolder.ObjectValue);
  591.                                     }
  592.                                     if (tempObjectHolder.RequiresValueTypeFixup) {
  593.                                         tempObjectHolder.ValueTypeFixupPerformed = true;
  594.                                     }
  595.                                 }
  596.                                 else {
  597.                                     throw new SerializationException(Environment.GetResourceString("Serialization_UnableToFixup"));
  598.                                 }
  599.                                 break;
  600.                             default:
  601.                                 throw new SerializationException(Environment.GetResourceString("Serialization_UnableToFixup"));
  602.                                 break;
  603.                         }
  604.                         //Decrement our total number of fixups left to do.
  605.                         fixupsPerformed++;
  606.                         fixups.m_values[i] = null;
  607.                         if (!bObjectFullyComplete) {
  608.                             holder.DecrementFixupsRemaining(this);
  609.                             tempObjectHolder.RemoveDependency(holder.m_id);
  610.                         }
  611.                     }
  612.                 }
  613.             }
  614.            
  615.             m_fixupCount -= fixupsPerformed;
  616.            
  617.             if (fixups.m_count == fixupsPerformed) {
  618.                 holder.m_missingElements = null;
  619.             }
  620.         }
  621.        
  622.        
  623. /*========================DoNewlyRegisteredObjectFixups=========================
  624.         **Action:  This is called immediately after we register a new object.  Walk that objects
  625.         **        dependency list (if it has one) and decrement the counters on each object for
  626.         **        the number of unsatisfiable references.  If the count reaches 0, go ahead
  627.         **        and process the object.
  628.         **Returns: void
  629.         **Arguments: dependencies The list of dependent objects
  630.         **Exceptions: None.
  631.         ==============================================================================*/       
  632.         private void DoNewlyRegisteredObjectFixups(ObjectHolder holder)
  633.         {
  634.             ObjectHolder temp;
  635.            
  636.             if (holder.IsIncompleteObjectReference || holder.HasSurrogate) {
  637.                 BCLDebug.Trace("SER", "[ObjectManager.DoNewlyRegisteredObjectFixups]Object is an Incomplete Object Reference. Exiting.");
  638.                 return;
  639.             }
  640.            
  641.             LongList dependencies = holder.DependentObjects;
  642.            
  643.             //If we don't have any dependencies, we're done.
  644.             if (dependencies == null) {
  645.                 BCLDebug.Trace("SER", "[DoNewlyRegisteredObjectFixups]Exiting with no dependencies");
  646.                 return;
  647.             }
  648.            
  649.             //Walk all of the dependencies and decrement the counter on each of uncompleted objects.
  650.             //If one of the counters reaches 0, all of it's fields have been completed and we should
  651.             //go take care of its fixups.
  652.             BCLDebug.Trace("SER", "[ObjectManager.DoNewlyRegisteredObjectFixups]Object has ", dependencies.Count, " fixups registered");
  653.             dependencies.StartEnumeration();
  654.             while (dependencies.MoveNext()) {
  655.                 temp = FindObjectHolder(dependencies.Current);
  656.                 BCLDebug.Trace("SER", "[ObjectManager.DoNewlyRegisteredObjectFixups]Doing a fixup on object: ", temp.m_id);
  657.                 BCLDebug.Assert(temp.DirectlyDependentObjects > 0, "temp.m_missingElementsRemaining>0");
  658.                 temp.DecrementFixupsRemaining(this);
  659.                 if (((temp.DirectlyDependentObjects)) == 0) {
  660.                     BCLDebug.Trace("SER", "[DoNewlyRegisteredObjectFixups]Doing fixup for object ", temp.m_id);
  661.                     BCLDebug.Trace("SER", "[DoNewlyRegisteredObjectFixups]ObjectValue ", ((temp.ObjectValue == null) ? "<null>" : temp.ObjectValue));
  662.                     // If this is null, we have the case where a fixup was registered for a child, the object
  663.                     // required by the fixup was provided, and the object to be fixed hasn't yet been seen.
  664.                     if (temp.ObjectValue != null) {
  665.                         CompleteObject(temp, true);
  666.                     }
  667.                     else {
  668.                         temp.MarkForCompletionWhenAvailable();
  669.                     }
  670.                 }
  671.             }
  672.             BCLDebug.Trace("SER", "[ObjectManager.DoNewlyRegisteredObjectFixups]Exiting.");
  673.         }
  674.        
  675.         public virtual object GetObject(long objectID)
  676.         {
  677.             if (objectID <= 0) {
  678.                 throw new ArgumentOutOfRangeException("objectID", Environment.GetResourceString("ArgumentOutOfRange_ObjectID"));
  679.             }
  680.            
  681.             //Find the bin in which we're interested. IObjectReference's shouldn't be returned -- the graph
  682.             //needs to link to the objects to which they refer, not to the references themselves.
  683.             ObjectHolder holder = FindObjectHolder(objectID);
  684.            
  685.             BCLDebug.Trace("SER", "GetObject. objectID: ", objectID);
  686.            
  687.             if (holder == null || (holder.IsIncompleteObjectReference || holder.HasSurrogate)) {
  688.                 BCLDebug.Trace("SER", "GetObject. holder: null or IncompleteObjectReference");
  689.                 return null;
  690.             }
  691.            
  692.             BCLDebug.Trace("SER", "GetObject. holder contains: ", ((holder.ObjectValue == null) ? "<null>" : holder.ObjectValue));
  693.             return holder.ObjectValue;
  694.         }
  695.        
  696.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  697.         public virtual void RegisterObject(object obj, long objectID)
  698.         {
  699.             RegisterObject(obj, objectID, null, 0, null);
  700.         }
  701.        
  702.        
  703.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  704.         public void RegisterObject(object obj, long objectID, SerializationInfo info)
  705.         {
  706.             RegisterObject(obj, objectID, info, 0, null);
  707.         }
  708.        
  709.        
  710.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  711.         public void RegisterObject(object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member)
  712.         {
  713.             RegisterObject(obj, objectID, info, idOfContainingObj, member, null);
  714.         }
  715.        
  716.        
  717.         internal void RegisterString(string obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member)
  718.         {
  719.             ObjectHolder temp;
  720.             BCLDebug.Assert(member == null || member is FieldInfo, "RegisterString - member is FieldInfo");
  721.             BCLDebug.Assert((FindObjectHolder(objectID) == null), "RegisterString - FindObjectHolder(objectID) == null");
  722.            
  723.             temp = new ObjectHolder(obj, objectID, info, null, idOfContainingObj, (FieldInfo)member, null);
  724.             AddObjectHolder(temp);
  725.             return;
  726.         }
  727.        
  728.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  729.         public void RegisterObject(object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member, int[] arrayIndex)
  730.         {
  731.             ObjectHolder temp;
  732.             ISerializationSurrogate surrogate = null;
  733.             ISurrogateSelector useless;
  734.            
  735.             if (obj == null) {
  736.                 throw new ArgumentNullException("obj");
  737.             }
  738.             if (objectID <= 0) {
  739.                 throw new ArgumentOutOfRangeException("objectID", Environment.GetResourceString("ArgumentOutOfRange_ObjectID"));
  740.             }
  741.            
  742.             if (member != null && !(member is RuntimeFieldInfo) && !(member is SerializationFieldInfo)) {
  743.                 throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMemberInfo"));
  744.             }
  745.            
  746.             if (m_selector != null) {
  747.                 Type selectorType = null;
  748.                 if (CanCallGetType(obj)) {
  749.                     selectorType = obj.GetType();
  750.                 }
  751.                 else {
  752.                     selectorType = typeof(MarshalByRefObject);
  753.                 }
  754.                
  755.                 BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]ID: ", objectID, "\tType: ", selectorType, "\tValue: ", obj);
  756.                
  757.                 //If we need a surrogate for this object, lets find it now.
  758.                 surrogate = m_selector.GetSurrogate(selectorType, m_context, out useless);
  759.             }
  760.            
  761.             //The object is interested in DeserializationEvents so lets register it.
  762.             if (obj is IDeserializationCallback) {
  763.                 DeserializationEventHandler d = new DeserializationEventHandler(((IDeserializationCallback)obj).OnDeserialization);
  764.                 AddOnDeserialization(d);
  765.             }
  766.            
  767.             //Formatter developers may cache and reuse arrayIndex in their code.
  768.             //So that we don't get bitten by this, take a copy up front.
  769.             if (arrayIndex != null) {
  770.                 arrayIndex = (int[])arrayIndex.Clone();
  771.             }
  772.            
  773.             temp = FindObjectHolder(objectID);
  774.             //This is the first time which we've seen the object, we need to create a new holder.
  775.             if (temp == null) {
  776.                 BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Adding a new object holder for ", objectID, "\tValueType: ", obj.GetType());
  777.                
  778.                 temp = new ObjectHolder(obj, objectID, info, surrogate, idOfContainingObj, (FieldInfo)member, arrayIndex);
  779.                 AddObjectHolder(temp);
  780.                 if (temp.RequiresDelayedFixup) {
  781.                     SpecialFixupObjects.Add(temp);
  782.                 }
  783.                 // We cannot compute whether this has any fixups required or not
  784.                 AddOnDeserialized(obj);
  785.                 return;
  786.             }
  787.            
  788.             //If the object isn't null, we've registered this before. Not good.
  789.             if (temp.ObjectValue != null) {
  790.                 throw new SerializationException(Environment.GetResourceString("Serialization_RegisterTwice"));
  791.             }
  792.            
  793.             //Complete the data in the ObjectHolder
  794.             temp.UpdateData(obj, info, surrogate, idOfContainingObj, (FieldInfo)member, arrayIndex, this);
  795.            
  796.             // The following case will only be true when somebody has registered a fixup on an object before
  797.             // registering the object itself. I don't believe that most well-behaved formatters will do this,
  798.             // but we need to allow it anyway. We will walk the list of fixups which have been recorded on
  799.             // the new object and fix those that we can. Because the user could still register later fixups
  800.             // on this object, we won't call any implementations of ISerializable now. If that's required,
  801.             // it will have to be handled by the code in DoFixups.
  802.             // README README: We have to do the UpdateData before
  803.             if (temp.DirectlyDependentObjects > 0) {
  804.                 CompleteObject(temp, false);
  805.             }
  806.            
  807.             if (temp.RequiresDelayedFixup) {
  808.                 BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Tracking incomplete objref for element: ", temp.m_id);
  809.                 SpecialFixupObjects.Add(temp);
  810.             }
  811.            
  812.             if (temp.CompletelyFixed) {
  813.                 //Here's where things get tricky. If this isn't an instance of IObjectReference, we need to walk it's fixup
  814.                 //chain and decrement the counters on anything that has reached 0. Once we've notified all of the dependencies,
  815.                 //we can simply clear the list of dependent objects.
  816.                 BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Calling DoNewlyRegisteredObjectFixups for element: ", temp.m_id);
  817.                 DoNewlyRegisteredObjectFixups(temp);
  818.                 temp.DependentObjects = null;
  819.             }
  820.            
  821.             //Register the OnDeserialized methods to be invoked after deserialization is complete
  822.             if (temp.TotalDependentObjects > 0) {
  823.                 AddOnDeserialized(obj);
  824.             }
  825.             else {
  826.                 RaiseOnDeserializedEvent(obj);
  827.             }
  828.            
  829.            
  830.             BCLDebug.Trace("SER", "[ObjectManager.RegisterObject]Exiting.");
  831.         }
  832.        
  833. /*=========================CompleteISerializableObject==========================
  834.         **Action: Completes an object implementing ISerializable.  This will involve calling that
  835.         **        objects constructor which takes an instance of ISerializable and a StreamingContext.
  836.         **Returns: void.
  837.         **Arguments: Obj    --  The object to be completed.
  838.         **          info    --  The SerializationInfo containing all info for obj.
  839.         **          context --  The streaming context in which the serialization is taking place.
  840.         **Exceptions: ArgumentNullException if obj is null
  841.         **            ArgumentException if obj does not implement ISerializable.
  842.         ==============================================================================*/       
  843.         internal void CompleteISerializableObject(object obj, SerializationInfo info, StreamingContext context)
  844.         {
  845.             RuntimeConstructorInfo constInfo = null;
  846.            
  847.            
  848.             if (obj == null) {
  849.                 throw new ArgumentNullException("obj");
  850.             }
  851.            
  852.             if (!(obj is ISerializable)) {
  853.                 throw new ArgumentException(Environment.GetResourceString("Serialization_NotISer"));
  854.             }
  855.            
  856.             Type t = obj.GetType();
  857.            
  858.             try {
  859.                 constInfo = GetConstructor(t);
  860.             }
  861.             catch (Exception e) {
  862.                 BCLDebug.Trace("SER", "[CompleteISerializableObject]Unable to get constructor for: ", t);
  863.                 BCLDebug.Trace("SER", "[CompleteISerializableObject]Stack trace was: ", e);
  864.                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ConstructorNotFound"), t), e);
  865.             }
  866.            
  867.             constInfo.SerializationInvoke(obj, info, context);
  868.         }
  869.        
  870.        
  871. /*================================GetConstructor================================
  872.         **Action:
  873.         **Returns:
  874.         **Arguments:
  875.         **Exceptions:
  876.         ==============================================================================*/       
  877.         static internal RuntimeConstructorInfo GetConstructor(Type t)
  878.         {
  879.             return GetConstructor(t, SIConstructorTypes);
  880.         }
  881.        
  882.         static internal RuntimeConstructorInfo GetConstructor(Type t, Type[] ctorParams)
  883.         {
  884.             BCLDebug.Assert(t != null, "[GetConstructor]t!=null");
  885.             BCLDebug.Assert(t is RuntimeType, "[GetConstructor]t is RuntimeType");
  886.             RuntimeConstructorInfo ci;
  887.            
  888.             if ((ci = (RuntimeConstructorInfo)t.Cache[CacheObjType.ConstructorInfo]) == null) {
  889.                 RuntimeType rt = (RuntimeType)t;
  890.                 ci = rt.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, ctorParams, null) as RuntimeConstructorInfo;
  891.                 if (ci == null) {
  892.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ConstructorNotFound"), t.FullName));
  893.                 }
  894.                
  895.                 t.Cache[CacheObjType.ConstructorInfo] = ci;
  896.             }
  897.            
  898.             return ci;
  899.         }
  900.        
  901.         public virtual void DoFixups()
  902.         {
  903.             ObjectHolder temp;
  904.             int fixupCount = -1;
  905.            
  906.             BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Entering");
  907.            
  908.             //The first thing that we need to do is fixup all of the objects which implement
  909.             //IObjectReference. This is complicated by the fact that we need to deal with IReferenceObjects
  910.             //objects that have a reference to an object implementing IObjectReference. We continually
  911.             //walk over the list of objects until we've completed all of the object references or until
  912.             //we can't resolve any more (which may happen if we have two objects implementing IObjectReference
  913.             //which have a circular dependency on each other). We don't explicitly catch the later case here,
  914.             //it will be caught when we try to do the rest of the fixups and discover that we have some that
  915.             //can't be completed.
  916.             while (fixupCount != 0) {
  917.                 fixupCount = 0;
  918.                 //Walk all of the IObjectReferences and ensure that they've been properly completed.
  919.                 ObjectHolderListEnumerator fixupObjectsEnum = SpecialFixupObjects.GetFixupEnumerator();
  920.                 while (fixupObjectsEnum.MoveNext()) {
  921.                     temp = fixupObjectsEnum.Current;
  922.                     if (temp.ObjectValue == null) {
  923.                         BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Object with id: ", temp.m_id, " not found.");
  924.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ObjectNotSupplied"), temp.m_id));
  925.                     }
  926.                     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);
  927.                     if (temp.TotalDependentObjects == 0) {
  928.                         if (temp.RequiresSerInfoFixup) {
  929.                             FixupSpecialObject(temp);
  930.                             fixupCount++;
  931.                         }
  932.                         else if (!temp.IsIncompleteObjectReference) {
  933.                             CompleteObject(temp, true);
  934.                         }
  935.                        
  936.                         if (temp.IsIncompleteObjectReference && ResolveObjectReference(temp)) {
  937.                             fixupCount++;
  938.                         }
  939.                     }
  940.                 }
  941.             }
  942.            
  943.             BCLDebug.Assert(m_fixupCount >= 0, "[ObjectManager.DoFixups]m_fixupCount>=0");
  944.            
  945.             //If our count is 0, we're done and should just return
  946.             if (m_fixupCount == 0) {
  947.                 BCLDebug.Trace("SER", "[ObjectManager.DoFixups]All fixups completed. We don't need to walk the list.");
  948.                 if (TopObject is TypeLoadExceptionHolder)
  949.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_TypeLoadFailure"), ((TypeLoadExceptionHolder)TopObject).TypeName));
  950.                 return;
  951.             }
  952.            
  953.             //If our count isn't 0, we had at least one case where an object referenced another object twice.
  954.             //Walk the entire list until the count is 0 or until we find an object which we can't complete.
  955.             BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Remaining object length is: ", m_objects.Length);
  956.             for (int i = 0; i < m_objects.Length; i++) {
  957.                 temp = m_objects[i];
  958.                 while (temp != null) {
  959.                     if (temp.TotalDependentObjects > 0)/*|| temp.m_missingElements!=null*/ {
  960.                         BCLDebug.Trace("SER", "[ObjectManager.DoFixups]Doing a delayed fixup on object ", temp.m_id);
  961.                         CompleteObject(temp, true);
  962.                     }
  963.                     temp = temp.m_next;
  964.                 }
  965.                 if (m_fixupCount == 0) {
  966.                     return;
  967.                 }
  968.             }
  969.            
  970.             // this assert can be trigered by user code that manages fixups manually
  971.             BCLDebug.Correctness(false, "[ObjectManager.DoFixups] Fixup counting is incorrect.");
  972.             throw new SerializationException(Environment.GetResourceString("Serialization_IncorrectNumberOfFixups"));
  973.         }
  974.        
  975. /*================================RegisterFixup=================================
  976.         **Action: Do the actual grunt work of recording a fixup and registering the dependency.
  977.         **        Create the necessary ObjectHolders and use them to do the addition.
  978.         **Returns: void
  979.         **Arguments: fixup -- The FixupHolder to be added.
  980.         **          objectToBeFixed -- The id of the object requiring the fixup.
  981.         **          objectRequired -- The id of the object required to do the fixup.
  982.         **Exceptions: None.  This is internal-only, so all checking should have been done by this time.
  983.         ==============================================================================*/       
  984.         private void RegisterFixup(FixupHolder fixup, long objectToBeFixed, long objectRequired)
  985.         {
  986.             //Record the fixup with the object that needs it.
  987.             ObjectHolder ohToBeFixed = FindOrCreateObjectHolder(objectToBeFixed);
  988.             ObjectHolder ohRequired;
  989.            
  990.             if (ohToBeFixed.RequiresSerInfoFixup && fixup.m_fixupType == FixupHolder.MemberFixup) {
  991.                 throw new SerializationException(Environment.GetResourceString("Serialization_InvalidFixupType"));
  992.             }
  993.            
  994.             //Add the fixup to the list.
  995.             ohToBeFixed.AddFixup(fixup, this);
  996.            
  997.             //Find the object on which we're dependent and note the dependency.
  998.             //These dependencies will be processed when the object is supplied.
  999.             ohRequired = FindOrCreateObjectHolder(objectRequired);
  1000.            
  1001.             ohRequired.AddDependency(objectToBeFixed);
  1002.            
  1003.             m_fixupCount++;
  1004.         }
  1005.        
  1006.         public virtual void RecordFixup(long objectToBeFixed, MemberInfo member, long objectRequired)
  1007.         {
  1008.            
  1009.             //Verify our arguments
  1010.             if (objectToBeFixed <= 0 || objectRequired <= 0) {
  1011.                 throw new ArgumentOutOfRangeException(((objectToBeFixed <= 0) ? "objectToBeFixed" : "objectRequired"), Environment.GetResourceString("Serialization_IdTooSmall"));
  1012.             }
  1013.            
  1014.             if (member == null) {
  1015.                 throw new ArgumentNullException("member");
  1016.             }
  1017.            
  1018.             if (!(member is RuntimeFieldInfo) && !(member is SerializationFieldInfo)) {
  1019.                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_InvalidType"), member.GetType().ToString()));
  1020.             }
  1021.            
  1022.            
  1023.             BCLDebug.Trace("SER", "RecordFixup. ObjectToBeFixed: ", objectToBeFixed, "\tMember: ", member.Name, "\tRequiredObject: ", objectRequired);
  1024.            
  1025.             //Create a new fixup holder
  1026.             FixupHolder fixup = new FixupHolder(objectRequired, member, FixupHolder.MemberFixup);
  1027.            
  1028.             RegisterFixup(fixup, objectToBeFixed, objectRequired);
  1029.         }
  1030.        
  1031.        
  1032. /*==============================RecordDelayedFixup==============================
  1033.         **Action:
  1034.         **Returns:
  1035.         **Arguments:
  1036.         **Exceptions:
  1037.         ==============================================================================*/       
  1038.         public virtual void RecordDelayedFixup(long objectToBeFixed, string memberName, long objectRequired)
  1039.         {
  1040.             //Verify our arguments
  1041.             if (objectToBeFixed <= 0 || objectRequired <= 0) {
  1042.                 throw new ArgumentOutOfRangeException(((objectToBeFixed <= 0) ? "objectToBeFixed" : "objectRequired"), Environment.GetResourceString("Serialization_IdTooSmall"));
  1043.             }
  1044.            
  1045.             if (memberName == null) {
  1046.                 throw new ArgumentNullException("memberName");
  1047.             }
  1048.            
  1049.             BCLDebug.Trace("SER", "RecordDelayedFixup. ObjectToBeFixed: ", objectToBeFixed, "\tMember: ", memberName, "\tRequiredObject: ", objectRequired);
  1050.            
  1051.             //Create a new fixup holder
  1052.             FixupHolder fixup = new FixupHolder(objectRequired, memberName, FixupHolder.DelayedFixup);
  1053.            
  1054.             RegisterFixup(fixup, objectToBeFixed, objectRequired);
  1055.         }
  1056.        
  1057. /*===========================RecordArrayElementFixup============================
  1058.         **Action:
  1059.         **Returns:
  1060.         **Arguments:
  1061.         **Exceptions:
  1062.         ==============================================================================*/       
  1063.         public virtual void RecordArrayElementFixup(long arrayToBeFixed, int index, long objectRequired)
  1064.         {
  1065.             int[] indexArray = new int[1];
  1066.             indexArray[0] = index;
  1067.            
  1068.             BCLDebug.Trace("SER", "RecordArrayElementFixup. ObjectToBeFixed: ", arrayToBeFixed, "\tIndex: ", index, "\tRequiredObject: ", objectRequired);
  1069.            
  1070.             RecordArrayElementFixup(arrayToBeFixed, indexArray, objectRequired);
  1071.         }
  1072.        
  1073.         public virtual void RecordArrayElementFixup(long arrayToBeFixed, int[] indices, long objectRequired)
  1074.         {
  1075.             //Verify our arguments
  1076.             if (arrayToBeFixed <= 0 || objectRequired <= 0) {
  1077.                 throw new ArgumentOutOfRangeException(((arrayToBeFixed <= 0) ? "objectToBeFixed" : "objectRequired"), Environment.GetResourceString("Serialization_IdTooSmall"));
  1078.             }
  1079.            
  1080.             if (indices == null) {
  1081.                 throw new ArgumentNullException("indices");
  1082.             }
  1083.            
  1084.             BCLDebug.Trace("SER", "RecordArrayElementFixup. ArrayToBeFixed: ", arrayToBeFixed, "\tRequiredObject: ", objectRequired);
  1085.             FixupHolder fixup = new FixupHolder(objectRequired, indices, FixupHolder.ArrayFixup);
  1086.             RegisterFixup(fixup, arrayToBeFixed, objectRequired);
  1087.         }
  1088.        
  1089.        
  1090. /*==========================RaiseDeserializationEvent===========================
  1091.         **Action:Raises the deserialization event to any registered object which implements
  1092.         **      IDeserializationCallback. 
  1093.         **Returns: void
  1094.         **Arguments: none
  1095.         **Exceptions: None
  1096.         ==============================================================================*/       
  1097.         public virtual void RaiseDeserializationEvent()
  1098.         {
  1099.             // Invoke OnDerserialized event if applicable
  1100.             if (m_onDeserializedHandler != null) {
  1101.                 m_onDeserializedHandler(m_context);
  1102.             }
  1103.            
  1104.             if (m_onDeserializationHandler != null) {
  1105.                 m_onDeserializationHandler(null);
  1106.             }
  1107.         }
  1108.        
  1109.         internal virtual void AddOnDeserialization(DeserializationEventHandler handler)
  1110.         {
  1111.             m_onDeserializationHandler = (DeserializationEventHandler)Delegate.Combine(m_onDeserializationHandler, handler);
  1112.         }
  1113.        
  1114.         internal virtual void RemoveOnDeserialization(DeserializationEventHandler handler)
  1115.         {
  1116.             m_onDeserializationHandler = (DeserializationEventHandler)Delegate.Remove(m_onDeserializationHandler, handler);
  1117.         }
  1118.        
  1119.         internal virtual void AddOnDeserialized(object obj)
  1120.         {
  1121.             SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType());
  1122.             m_onDeserializedHandler = cache.AddOnDeserialized(obj, m_onDeserializedHandler);
  1123.         }
  1124.        
  1125.         internal virtual void RaiseOnDeserializedEvent(object obj)
  1126.         {
  1127.             SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType());
  1128.             cache.InvokeOnDeserialized(obj, m_context);
  1129.         }
  1130.        
  1131.         public void RaiseOnDeserializingEvent(object obj)
  1132.         {
  1133.             // Run the OnDeserializing methods
  1134.             SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType());
  1135.             cache.InvokeOnDeserializing(obj, m_context);
  1136.         }
  1137.     }
  1138.    
  1139.     internal sealed class ObjectHolder
  1140.     {
  1141.         internal const int INCOMPLETE_OBJECT_REFERENCE = 1;
  1142.         internal const int HAS_ISERIALIZABLE = 2;
  1143.         internal const int HAS_SURROGATE = 4;
  1144.         internal const int REQUIRES_VALUETYPE_FIXUP = 8;
  1145.         internal const int REQUIRES_DELAYED_FIXUP = HAS_ISERIALIZABLE | HAS_SURROGATE | INCOMPLETE_OBJECT_REFERENCE;
  1146.         internal const int SER_INFO_FIXED = 16384;
  1147.         internal const int VALUETYPE_FIXUP_PERFORMED = 32768;
  1148.        
  1149.         private object m_object;
  1150.         internal long m_id;
  1151.         private int m_missingElementsRemaining;
  1152.         private int m_missingDecendents;
  1153.         internal SerializationInfo m_serInfo;
  1154.         internal ISerializationSurrogate m_surrogate;
  1155.         internal FixupHolderList m_missingElements;
  1156.         internal LongList m_dependentObjects;
  1157.         internal ObjectHolder m_next;
  1158.         internal int m_flags;
  1159.         private bool m_markForFixupWhenAvailable;
  1160.         private ValueTypeFixupInfo m_valueFixup;
  1161.         private TypeLoadExceptionHolder m_typeLoad = null;
  1162.         private bool m_reachable = false;
  1163.        
  1164.         internal ObjectHolder(long objID) : this(null, objID, null, null, 0, null, null)
  1165.         {
  1166.         }
  1167.        
  1168.         internal ObjectHolder(object obj, long objID, SerializationInfo info, ISerializationSurrogate surrogate, long idOfContainingObj, FieldInfo field, int[] arrayIndex)
  1169.         {
  1170.             BCLDebug.Assert(objID >= 0, "objID>=0");
  1171.            
  1172.             m_object = obj;
  1173.             //May be null;
  1174.             m_id = objID;
  1175.            
  1176.             m_flags = 0;
  1177.             m_missingElementsRemaining = 0;
  1178.             m_missingDecendents = 0;
  1179.             m_dependentObjects = null;
  1180.             m_next = null;
  1181.            
  1182.             m_serInfo = info;
  1183.             m_surrogate = surrogate;
  1184.             m_markForFixupWhenAvailable = false;
  1185.            
  1186.             if (obj is TypeLoadExceptionHolder) {
  1187.                 m_typeLoad = (TypeLoadExceptionHolder)obj;
  1188.             }
  1189.            
  1190.            
  1191.             if (idOfContainingObj != 0 && ((field != null && field.FieldType.IsValueType) || arrayIndex != null)) {
  1192.                 if (idOfContainingObj == objID) {
  1193.                     throw new SerializationException(Environment.GetResourceString("Serialization_ParentChildIdentical"));
  1194.                 }
  1195.                
  1196.                 m_valueFixup = new ValueTypeFixupInfo(idOfContainingObj, field, arrayIndex);
  1197.             }
  1198.            
  1199.             SetFlags();
  1200.         }
  1201.        
  1202.         internal ObjectHolder(string obj, long objID, SerializationInfo info, ISerializationSurrogate surrogate, long idOfContainingObj, FieldInfo field, int[] arrayIndex)
  1203.         {
  1204.             BCLDebug.Assert(objID >= 0, "objID>=0");
  1205.            
  1206.             m_object = obj;
  1207.             //May be null;
  1208.             m_id = objID;
  1209.            
  1210.             m_flags = 0;
  1211.             m_missingElementsRemaining = 0;
  1212.             m_missingDecendents = 0;
  1213.             m_dependentObjects = null;
  1214.             m_next = null;
  1215.            
  1216.             m_serInfo = info;
  1217.             m_surrogate = surrogate;
  1218.             m_markForFixupWhenAvailable = false;
  1219.            
  1220.             if (idOfContainingObj != 0 && arrayIndex != null) {
  1221.                 m_valueFixup = new ValueTypeFixupInfo(idOfContainingObj, field, arrayIndex);
  1222.             }
  1223.            
  1224.             if (m_valueFixup != null) {
  1225.                 m_flags |= REQUIRES_VALUETYPE_FIXUP;
  1226.             }
  1227.         }
  1228.        
  1229.         private void IncrementDescendentFixups(int amount)
  1230.         {
  1231.             m_missingDecendents += amount;
  1232.         }
  1233.        
  1234.         internal void DecrementFixupsRemaining(ObjectManager manager)
  1235.         {
  1236.             m_missingElementsRemaining--;
  1237.            
  1238.             if (RequiresValueTypeFixup) {
  1239.                 UpdateDescendentDependencyChain(-1, manager);
  1240.             }
  1241.         }
  1242.        
  1243. /*===============================RemoveDependency===============================
  1244.         **Action: Removes a dependency of the object represented in this holder.
  1245.         **        This is normally the result of the dependency having been filled when
  1246.         **        the object is going to be only partially completed.  If we plan to fully
  1247.         **        update the object, we do not take the work to do this.
  1248.         **Returns: void.
  1249.         **Arguments: id -- The id of the object for which to remove the dependency.
  1250.         **Exceptions: None, error handling through asserts.
  1251.         ==============================================================================*/       
  1252.         internal void RemoveDependency(long id)
  1253.         {
  1254.             BCLDebug.Assert(m_dependentObjects != null, "[ObjectHolder.RemoveDependency]m_dependentObjects!=null");
  1255.             BCLDebug.Assert(id >= 0, "[ObjectHolder.RemoveDependency]id>=0");
  1256.             m_dependentObjects.RemoveElement(id);
  1257.         }
  1258.        
  1259. /*===================================AddFixup===================================
  1260.         **Action: Note a fixup that has to be done before this object can be completed.
  1261.         **        Fixups are things that need to happen when other objects in the graph
  1262.         **        are added.  Dependencies are things that need to happen when this object
  1263.         **        is added.
  1264.         **Returns: void
  1265.         **Arguments: fixup -- The fixup holder containing enough information to complete the fixup.
  1266.         **Exceptions: None.
  1267.         ==============================================================================*/       
  1268.         internal void AddFixup(FixupHolder fixup, ObjectManager manager)
  1269.         {
  1270.             if (m_missingElements == null) {
  1271.                 m_missingElements = new FixupHolderList();
  1272.             }
  1273.             m_missingElements.Add(fixup);
  1274.             m_missingElementsRemaining++;
  1275.            
  1276.             if (RequiresValueTypeFixup) {
  1277.                 UpdateDescendentDependencyChain(1, manager);
  1278.             }
  1279.         }
  1280.        
  1281. /*==========================UpdateTotalDependencyChain==========================
  1282.         **Action: Updates the total list of dependencies to account for a fixup being added
  1283.         **        or completed in a child value class.  This will update all value classes
  1284.         **        containing that child and the object which contains all of them. 
  1285.         **Returns: void
  1286.         **Arguments: amount -- the amount by which to increment (or decrement) the dependency chain.
  1287.         **          manager -- The ObjectManager used to lookup other objects up the chain.
  1288.         **Exceptions: None.  Asserts only.
  1289.         ==============================================================================*/       
  1290.         private void UpdateDescendentDependencyChain(int amount, ObjectManager manager)
  1291.         {
  1292.             ObjectHolder holder = this;
  1293.            
  1294.             //This loop walks one more object up the chain than there are valuetypes. This
  1295.             //is because we need to increment the TotalFixups in the holders as well.
  1296.             do {
  1297.                 holder = manager.FindOrCreateObjectHolder(holder.ContainerID);
  1298.                 BCLDebug.Trace("SER", "[ObjectManager.UpdateDescendentDependencyChain]Looking for holder with id: ", holder.ContainerID);
  1299.                 BCLDebug.Assert(holder != null, "[ObjectHolder.UpdateTotalDependencyChain]holder!=null");
  1300.                 holder.IncrementDescendentFixups(amount);
  1301.             }
  1302.             while (holder.RequiresValueTypeFixup);
  1303.         }
  1304.        
  1305. /*================================AddDependency=================================
  1306.         **Action: Note an object which is dependent on the one which will be contained in
  1307.         **        this ObjectHolder.  Dependencies should only be added if the object hasn't
  1308.         **        yet been added.  NB: An incomplete object counts as having no object.
  1309.         **Returns: void
  1310.         **Arguments: dependentObject -- the id of the object which is dependent on this object being provided.
  1311.         **Exceptions: None.
  1312.         ==============================================================================*/       
  1313.         internal void AddDependency(long dependentObject)
  1314.         {
  1315.             if (m_dependentObjects == null) {
  1316.                 m_dependentObjects = new LongList();
  1317.             }
  1318.             m_dependentObjects.Add(dependentObject);
  1319.         }
  1320.        
  1321.        
  1322. /*==================================UpdateData==================================
  1323.         **Action: Update the data in the object holder.  This should be called when the object
  1324.         **        is finally registered.  Presumably the ObjectHolder was created to track
  1325.         **        some dependencies or preregistered fixups and we now need to actually record the
  1326.         **        object and other associated data.  We take this opportunity to set the flags
  1327.         **        so that we can do some faster processing in the future.
  1328.         **Returns: void
  1329.         **Arguments: obj -- The object being held by this object holder. (This should no longer be null).
  1330.         **          info --The SerializationInfo associated with this object, only required if we're doing delayed fixups.
  1331.         **          surrogate -- The surrogate handling this object.  May be null.
  1332.         **          idOfContainer -- The id of the object containing this one if this is a valuetype.
  1333.         **          member -- the MemberInfo of this object's position in it's container if this is a valuetype.
  1334.         **          manager -- the ObjectManager being used to track these ObjectHolders.
  1335.         **Exceptions: None. Asserts only.
  1336.         ==============================================================================*/       
  1337.         internal void UpdateData(object obj, SerializationInfo info, ISerializationSurrogate surrogate, long idOfContainer, FieldInfo field, int[] arrayIndex, ObjectManager manager)
  1338.         {
  1339.             BCLDebug.Assert(obj != null, "obj!=null");
  1340.             BCLDebug.Assert(m_id > 0, "m_id>0");
  1341.            
  1342.             //Record the fields that we can.
  1343.             SetObjectValue(obj, manager);
  1344.             m_serInfo = info;
  1345.             m_surrogate = surrogate;
  1346.            
  1347.             if (idOfContainer != 0 && ((field != null && field.FieldType.IsValueType) || arrayIndex != null)) {
  1348.                 if (idOfContainer == m_id) {
  1349.                     throw new SerializationException(Environment.GetResourceString("Serialization_ParentChildIdentical"));
  1350.                 }
  1351.                 m_valueFixup = new ValueTypeFixupInfo(idOfContainer, field, arrayIndex);
  1352.             }
  1353.            
  1354.             SetFlags();
  1355.            
  1356.             if (RequiresValueTypeFixup) {
  1357.                 UpdateDescendentDependencyChain(m_missingElementsRemaining, manager);
  1358.             }
  1359.         }
  1360.        
  1361.         internal void MarkForCompletionWhenAvailable()
  1362.         {
  1363.             m_markForFixupWhenAvailable = true;
  1364.         }
  1365.        
  1366.        
  1367. /*===================================SetFlags===================================
  1368.         **Action: An internal-only routine to set the flags based upon the data contained in
  1369.         **        the ObjectHolder
  1370.         **Returns: Void
  1371.         **Arguments: None
  1372.         **Exceptions: None
  1373.         ==============================================================================*/       
  1374.         internal void SetFlags()
  1375.         {
  1376.             if (m_object is IObjectReference) {
  1377.                 m_flags |= INCOMPLETE_OBJECT_REFERENCE;
  1378.             }
  1379.            
  1380.             m_flags &= ~(HAS_ISERIALIZABLE | HAS_SURROGATE);
  1381.             if (m_surrogate != null)
  1382.                 m_flags |= HAS_SURROGATE;
  1383.             else if (m_object is ISerializable)
  1384.                 m_flags |= HAS_ISERIALIZABLE;
  1385.            
  1386.             if (m_valueFixup != null) {
  1387.                 m_flags |= REQUIRES_VALUETYPE_FIXUP;
  1388.             }
  1389.         }
  1390.        
  1391.         internal bool IsIncompleteObjectReference {
  1392. /*| HAS_SURROGATE*/            get { return (m_flags & (INCOMPLETE_OBJECT_REFERENCE)) != 0; }
  1393.             set {
  1394.                 if (value) {
  1395.                     m_flags |= INCOMPLETE_OBJECT_REFERENCE;
  1396.                 }
  1397.                 else {
  1398.                     m_flags &= ~INCOMPLETE_OBJECT_REFERENCE;
  1399.                 }
  1400.             }
  1401.         }
  1402.        
  1403.         internal bool RequiresDelayedFixup {
  1404.             get { return (m_flags & REQUIRES_DELAYED_FIXUP) != 0; }
  1405.         }
  1406.        
  1407.         internal bool RequiresValueTypeFixup {
  1408.             get { return (m_flags & REQUIRES_VALUETYPE_FIXUP) != 0; }
  1409.         }
  1410.        
  1411.         // ValueTypes which require fixups are initially handed to the ObjectManager
  1412.         // as boxed objects. When they're still boxed objects, we should just do fixups
  1413.         // on them like we would any other object. As soon as they're pushed into their
  1414.         // containing object we set ValueTypeFixupPerformed to true and have to go through
  1415.         // a more complicated path to set fixed up valuetype objects.
  1416.         // We check whether or not there are any dependent objects.
  1417.         internal bool ValueTypeFixupPerformed {
  1418.             get {
  1419.                 BCLDebug.Trace("SER", "[ObjectManager.ValueTypeFixupPerformed]Flags: ", m_flags & VALUETYPE_FIXUP_PERFORMED);
  1420.                 BCLDebug.Trace("SER", "[ObjectManager.ValueTypeFixupPerformed]DependentObjects: ", (m_dependentObjects == null) ? "<null>" : m_dependentObjects.Count.ToString());
  1421.                 return (((m_flags & VALUETYPE_FIXUP_PERFORMED) != 0) || (m_object != null && ((m_dependentObjects == null) || m_dependentObjects.Count == 0)));
  1422.             }
  1423.             set {
  1424.                 if (value) {
  1425.                     m_flags |= VALUETYPE_FIXUP_PERFORMED;
  1426.                 }
  1427.             }
  1428.         }
  1429.        
  1430.        
  1431.         internal bool HasISerializable {
  1432.             get { return (m_flags & HAS_ISERIALIZABLE) != 0; }
  1433.         }
  1434.        
  1435.         internal bool HasSurrogate {
  1436.             get { return (m_flags & HAS_SURROGATE) != 0; }
  1437.         }
  1438.        
  1439.        
  1440.         internal int DirectlyDependentObjects {
  1441.             get { return m_missingElementsRemaining; }
  1442.         }
  1443.        
  1444.        
  1445.         internal int TotalDependentObjects {
  1446.             get { return m_missingElementsRemaining + m_missingDecendents; }
  1447.         }
  1448.        
  1449.         internal bool Reachable {
  1450.             get { return m_reachable; }
  1451.             set { m_reachable = value; }
  1452.         }
  1453.        
  1454.         internal bool TypeLoadExceptionReachable {
  1455.             get { return m_typeLoad != null; }
  1456.         }
  1457.        
  1458.         internal TypeLoadExceptionHolder TypeLoadException {
  1459.             get { return m_typeLoad; }
  1460.             set { m_typeLoad = value; }
  1461.         }
  1462.        
  1463.        
  1464.         internal object ObjectValue {
  1465.             get { return m_object; }
  1466.         }
  1467.        
  1468.         internal void SetObjectValue(object obj, ObjectManager manager)
  1469.         {
  1470.             m_object = obj;
  1471.             if (obj == manager.TopObject)
  1472.                 m_reachable = true;
  1473.             if (obj is TypeLoadExceptionHolder)
  1474.                 m_typeLoad = (TypeLoadExceptionHolder)obj;
  1475.            
  1476.             if (m_markForFixupWhenAvailable) {
  1477.                 manager.CompleteObject(this, true);
  1478.             }
  1479.         }
  1480.        
  1481.         internal SerializationInfo SerializationInfo {
  1482.             get { return m_serInfo; }
  1483.            
  1484.             set { m_serInfo = value; }
  1485.         }
  1486.        
  1487.         internal ISerializationSurrogate Surrogate {
  1488.             get { return m_surrogate; }
  1489.         }
  1490.        
  1491.         internal LongList DependentObjects {
  1492.             get { return m_dependentObjects; }
  1493.             set { m_dependentObjects = value; }
  1494.         }
  1495.        
  1496.         internal bool RequiresSerInfoFixup {
  1497.             get {
  1498.                 if (((m_flags & HAS_SURROGATE) == 0) && ((m_flags & HAS_ISERIALIZABLE) == 0)) {
  1499.                     return false;
  1500.                 }
  1501.                
  1502.                 return (m_flags & SER_INFO_FIXED) == 0;
  1503.             }
  1504.             set {
  1505.                 if (!value) {
  1506.                     m_flags |= SER_INFO_FIXED;
  1507.                 }
  1508.                 else {
  1509.                     m_flags &= ~SER_INFO_FIXED;
  1510.                 }
  1511.             }
  1512.         }
  1513.        
  1514.         internal ValueTypeFixupInfo ValueFixup {
  1515.             get { return m_valueFixup; }
  1516.         }
  1517.        
  1518.         internal bool CompletelyFixed {
  1519.             get { return (!RequiresSerInfoFixup && !IsIncompleteObjectReference); }
  1520.         }
  1521.        
  1522.         internal long ContainerID {
  1523.             get {
  1524.                 if (m_valueFixup != null) {
  1525.                     return m_valueFixup.ContainerID;
  1526.                 }
  1527.                 return 0;
  1528.             }
  1529.         }
  1530.     }
  1531.    
  1532.     [Serializable()]
  1533.     internal class FixupHolder
  1534.     {
  1535.         internal const int ArrayFixup = 1;
  1536.         internal const int MemberFixup = 2;
  1537.         internal const int DelayedFixup = 4;
  1538.        
  1539.         internal long m_id;
  1540.         internal object m_fixupInfo;
  1541.         //This is either an array index, a String, or a MemberInfo
  1542.         internal int m_fixupType;
  1543.        
  1544.         internal FixupHolder(long id, object fixupInfo, int fixupType)
  1545.         {
  1546.             BCLDebug.Assert(id > 0, "id>0");
  1547.             BCLDebug.Assert(fixupInfo != null, "fixupInfo!=null");
  1548.             BCLDebug.Assert(fixupType == ArrayFixup || fixupType == MemberFixup || fixupType == DelayedFixup, "fixupType==ArrayFixup || fixupType == MemberFixup || fixupType==DelayedFixup");
  1549.            
  1550.             m_id = id;
  1551.             m_fixupInfo = fixupInfo;
  1552.             m_fixupType = fixupType;
  1553.         }
  1554.     }
  1555.    
  1556.     [Serializable()]
  1557.     internal class FixupHolderList
  1558.     {
  1559.         internal const int InitialSize = 2;
  1560.        
  1561.         internal FixupHolder[] m_values;
  1562.         internal int m_count;
  1563.        
  1564.         internal FixupHolderList() : this(InitialSize)
  1565.         {
  1566.         }
  1567.        
  1568.         internal FixupHolderList(int startingSize)
  1569.         {
  1570.             m_count = 0;
  1571.             m_values = new FixupHolder[startingSize];
  1572.         }
  1573.        
  1574.         internal virtual void Add(long id, object fixupInfo)
  1575.         {
  1576.             if (m_count == m_values.Length) {
  1577.                 EnlargeArray();
  1578.             }
  1579.             m_values[m_count].m_id = id;
  1580.             m_values[m_count++].m_fixupInfo = fixupInfo;
  1581.         }
  1582.        
  1583.         internal virtual void Add(FixupHolder fixup)
  1584.         {
  1585.             if (m_count == m_values.Length) {
  1586.                 EnlargeArray();
  1587.             }
  1588.             m_values[m_count++] = fixup;
  1589.         }
  1590.        
  1591.         private void EnlargeArray()
  1592.         {
  1593.             int newLength = m_values.Length * 2;
  1594.             if (newLength < 0) {
  1595.                 if (newLength == Int32.MaxValue) {
  1596.                     throw new SerializationException(Environment.GetResourceString("Serialization_TooManyElements"));
  1597.                 }
  1598.                 newLength = Int32.MaxValue;
  1599.             }
  1600.            
  1601.             FixupHolder[] temp = new FixupHolder[newLength];
  1602.             Array.Copy(m_values, temp, m_count);
  1603.             m_values = temp;
  1604.         }
  1605.        
  1606.        
  1607.     }
  1608.    
  1609.     [Serializable()]
  1610.     internal class LongList
  1611.     {
  1612.         private const int InitialSize = 2;
  1613.        
  1614.         private long[] m_values;
  1615.         private int m_count;
  1616.         //The total number of valid items still in the list;
  1617.         private int m_totalItems;
  1618.         //The total number of allocated entries.
  1619.         //This includes space for items which have been marked as deleted.
  1620.         private int m_currentItem;
  1621.         //Used when doing an enumeration over the list.
  1622.         //
  1623.         // An m_currentItem of -1 indicates that the enumeration hasn't been started.
  1624.         // An m_values[xx] of -1 indicates that the item has been deleted.
  1625.         //
  1626.         internal LongList() : this(InitialSize)
  1627.         {
  1628.         }
  1629.        
  1630.         internal LongList(int startingSize)
  1631.         {
  1632.             m_count = 0;
  1633.             m_totalItems = 0;
  1634.             m_values = new long[startingSize];
  1635.         }
  1636.        
  1637.         internal void Add(long value)
  1638.         {
  1639.             if (m_totalItems == m_values.Length) {
  1640.                 EnlargeArray();
  1641.             }
  1642.             m_values[m_totalItems++] = value;
  1643.             m_count++;
  1644.         }
  1645.        
  1646.         internal int Count {
  1647.             get { return m_count; }
  1648.         }
  1649.        
  1650.         internal void StartEnumeration()
  1651.         {
  1652.             m_currentItem = -1;
  1653.         }
  1654.        
  1655.         internal bool MoveNext()
  1656.         {
  1657.             while (++m_currentItem < m_totalItems && m_values[m_currentItem] == -1) {
  1658.             }
  1659.             if (m_currentItem == m_totalItems) {
  1660.                 return false;
  1661.             }
  1662.             return true;
  1663.         }
  1664.        
  1665.         internal long Current {
  1666.             get {
  1667.                 BCLDebug.Assert(m_currentItem != -1, "[LongList.Current]m_currentItem!=-1");
  1668.                 BCLDebug.Assert(m_values[m_currentItem] != -1, "[LongList.Current]m_values[m_currentItem]!=-1");
  1669.                 return m_values[m_currentItem];
  1670.             }
  1671.         }
  1672.        
  1673.         internal bool RemoveElement(long value)
  1674.         {
  1675.             int i;
  1676.             for (i = 0; i < m_totalItems; i++) {
  1677.                 if (m_values[i] == value)
  1678.                     break;
  1679.             }
  1680.             if (i == m_totalItems) {
  1681.                 return false;
  1682.             }
  1683.             m_values[i] = -1;
  1684.             return true;
  1685.         }
  1686.        
  1687.         private void EnlargeArray()
  1688.         {
  1689.             BCLDebug.Trace("SER", "[LongList.EnlargeArray]Enlarging array of size ", m_values.Length);
  1690.             int newLength = m_values.Length * 2;
  1691.             if (newLength < 0) {
  1692.                 if (newLength == Int32.MaxValue) {
  1693.                     throw new SerializationException(Environment.GetResourceString("Serialization_TooManyElements"));
  1694.                 }
  1695.                 newLength = Int32.MaxValue;
  1696.             }
  1697.            
  1698.             long[] temp = new long[newLength];
  1699.             Array.Copy(m_values, temp, m_count);
  1700.             m_values = temp;
  1701.         }
  1702.     }
  1703.    
  1704.     internal class ObjectHolderList
  1705.     {
  1706.         internal const int DefaultInitialSize = 8;
  1707.        
  1708.         internal ObjectHolder[] m_values;
  1709.         internal int m_count;
  1710.        
  1711.         internal ObjectHolderList() : this(DefaultInitialSize)
  1712.         {
  1713.         }
  1714.        
  1715.         internal ObjectHolderList(int startingSize)
  1716.         {
  1717.             BCLDebug.Assert(startingSize > 0 && startingSize < 4096, "startingSize>0 && startingSize<0x1000");
  1718.            
  1719.             m_count = 0;
  1720.             m_values = new ObjectHolder[startingSize];
  1721.         }
  1722.        
  1723.         internal virtual void Add(ObjectHolder value)
  1724.         {
  1725.             if (m_count == m_values.Length) {
  1726.                 EnlargeArray();
  1727.             }
  1728.             m_values[m_count++] = value;
  1729.         }
  1730.        
  1731.        
  1732.         internal ObjectHolderListEnumerator GetFixupEnumerator()
  1733.         {
  1734.             return new ObjectHolderListEnumerator(this, true);
  1735.         }
  1736.        
  1737.         private void EnlargeArray()
  1738.         {
  1739.             BCLDebug.Trace("SER", "[ObjectHolderList.EnlargeArray]Enlarging array of size ", m_values.Length);
  1740.             int newLength = m_values.Length * 2;
  1741.             if (newLength < 0) {
  1742.                 if (newLength == Int32.MaxValue) {
  1743.                     throw new SerializationException(Environment.GetResourceString("Serialization_TooManyElements"));
  1744.                 }
  1745.                 newLength = Int32.MaxValue;
  1746.             }
  1747.            
  1748.             ObjectHolder[] temp = new ObjectHolder[newLength];
  1749.             Array.Copy(m_values, temp, m_count);
  1750.             m_values = temp;
  1751.         }
  1752.        
  1753.         internal int Version {
  1754.             get { return m_count; }
  1755.         }
  1756.        
  1757.         internal int Count {
  1758.             get { return m_count; }
  1759.         }
  1760.     }
  1761.    
  1762.     internal class ObjectHolderListEnumerator
  1763.     {
  1764.         bool m_isFixupEnumerator;
  1765.         ObjectHolderList m_list;
  1766.         int m_startingVersion;
  1767.         int m_currPos;
  1768.        
  1769.         internal ObjectHolderListEnumerator(ObjectHolderList list, bool isFixupEnumerator)
  1770.         {
  1771.             BCLDebug.Assert(list != null, "[ObjectHolderListEnumerator.ctor]list!=null");
  1772.             m_list = list;
  1773.             m_startingVersion = m_list.Version;
  1774.             m_currPos = -1;
  1775.             m_isFixupEnumerator = isFixupEnumerator;
  1776.         }
  1777.        
  1778.         internal bool MoveNext()
  1779.         {
  1780.             BCLDebug.Assert(m_startingVersion == m_list.Version, "[ObjectHolderListEnumerator.MoveNext]m_startingVersion==m_list.Version");
  1781.             if (m_isFixupEnumerator) {
  1782.                 while (++m_currPos < m_list.Count && m_list.m_values[m_currPos].CompletelyFixed) {
  1783.                 }
  1784.                 if (m_currPos == m_list.Count) {
  1785.                     return false;
  1786.                 }
  1787.                 return true;
  1788.             }
  1789.             else {
  1790.                 m_currPos++;
  1791.                 if (m_currPos == m_list.Count) {
  1792.                     return false;
  1793.                 }
  1794.                 return true;
  1795.             }
  1796.         }
  1797.        
  1798.         internal ObjectHolder Current {
  1799.             get {
  1800.                 BCLDebug.Assert(m_currPos != -1, "[ObjectHolderListEnumerator.Current]m_currPos!=-1");
  1801.                 BCLDebug.Assert(m_currPos < m_list.Count, "[ObjectHolderListEnumerator.Current]m_currPos<m_list.Count");
  1802.                 BCLDebug.Assert(m_startingVersion == m_list.Version, "[ObjectHolderListEnumerator.Current]m_startingVersion==m_list.Version");
  1803.                 return m_list.m_values[m_currPos];
  1804.             }
  1805.         }
  1806.     }
  1807.    
  1808.     internal class TypeLoadExceptionHolder
  1809.     {
  1810.         string m_typeName;
  1811.         internal TypeLoadExceptionHolder(string typeName)
  1812.         {
  1813.             m_typeName = typeName;
  1814.         }
  1815.        
  1816.         internal string TypeName {
  1817.             get { return m_typeName; }
  1818.         }
  1819.        
  1820.     }
  1821. }

Developer Fusion