The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization.Formatters.Binary \ ObjectReader

  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: ObjectReader
  18. **
  19. **
  20. ** Purpose: DeSerializes Binary Wire format
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System.Runtime.Serialization.Formatters.Binary
  25. {
  26.    
  27.     using System;
  28.     using System.Globalization;
  29.     using System.IO;
  30.     using System.Reflection;
  31.     using System.Collections;
  32.     using System.Text;
  33.     using System.Runtime.Remoting;
  34.     using System.Runtime.Remoting.Messaging;
  35.     using System.Runtime.Serialization;
  36.     using System.Security.Permissions;
  37.     using System.Security;
  38.     using System.Diagnostics;
  39.     using System.Resources;
  40.     using StackCrawlMark = System.Threading.StackCrawlMark;
  41.    
  42.     internal sealed class ObjectReader
  43.     {
  44.        
  45.         // System.Serializer information
  46.         internal Stream m_stream;
  47.         internal ISurrogateSelector m_surrogates;
  48.         internal StreamingContext m_context;
  49.         internal ObjectManager m_objectManager;
  50.         internal InternalFE formatterEnums;
  51.         internal SerializationBinder m_binder;
  52.        
  53.         // Top object and headers
  54.         internal long topId;
  55.         internal bool bSimpleAssembly = false;
  56.         internal object handlerObject;
  57.         internal object m_topObject;
  58.         internal Header[] headers;
  59.         internal HeaderHandler handler;
  60.         internal SerObjectInfoInit serObjectInfoInit;
  61.         internal IFormatterConverter m_formatterConverter;
  62.        
  63.         // Stack of Object ParseRecords
  64.         internal SerStack stack;
  65.        
  66.         // ValueType Fixup Stack
  67.         private SerStack valueFixupStack;
  68.        
  69.         // Cross AppDomain
  70.         internal object[] crossAppDomainArray;
  71.         //Set by the BinaryFormatter
  72.         //MethodCall and MethodReturn are handled special for perf reasons
  73.         private bool bMethodCall;
  74.         private bool bMethodReturn;
  75.         private bool bFullDeserialization;
  76.         private BinaryMethodCall binaryMethodCall;
  77.         private BinaryMethodReturn binaryMethodReturn;
  78.         private bool bIsCrossAppDomain;
  79.        
  80.         private Exception deserializationSecurityException;
  81.         private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
  82.        
  83.         private SerStack ValueFixupStack {
  84.             get {
  85.                 if (valueFixupStack == null)
  86.                     valueFixupStack = new SerStack("ValueType Fixup Stack");
  87.                 return valueFixupStack;
  88.             }
  89.         }
  90.        
  91.         internal object TopObject {
  92.             get { return m_topObject; }
  93.             set {
  94.                 m_topObject = value;
  95.                 if (m_objectManager != null)
  96.                     m_objectManager.TopObject = value;
  97.             }
  98.         }
  99.        
  100.         internal void SetMethodCall(BinaryMethodCall binaryMethodCall)
  101.         {
  102.             bMethodCall = true;
  103.             this.binaryMethodCall = binaryMethodCall;
  104.         }
  105.        
  106.         internal void SetMethodReturn(BinaryMethodReturn binaryMethodReturn)
  107.         {
  108.             bMethodReturn = true;
  109.             this.binaryMethodReturn = binaryMethodReturn;
  110.         }
  111.        
  112.        
  113.         internal ObjectReader(Stream stream, ISurrogateSelector selector, StreamingContext context, InternalFE formatterEnums, SerializationBinder binder)
  114.         {
  115.             SerTrace.Log(this, "Constructor ISurrogateSelector ", ((selector == null) ? "null selector " : "selector present"));
  116.            
  117.             if (stream == null) {
  118.                 throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream"));
  119.             }
  120.            
  121.             m_stream = stream;
  122.             m_surrogates = selector;
  123.             m_context = context;
  124.             m_binder = binder;
  125.            
  126.            
  127.             this.formatterEnums = formatterEnums;
  128.            
  129.             //SerTrace.Log( this, "Constructor formatterEnums.FEtopObject ",formatterEnums.FEtopObject);
  130.            
  131.         }
  132.        
  133.         // Deserialize the stream into an object graph.
  134.         internal object Deserialize(HeaderHandler handler, __BinaryParser serParser, bool fCheck, bool isCrossAppDomain, IMethodCallMessage methodCallMessage)
  135.         {
  136.             #if _DEBUG
  137.             SerTrace.Log(this, "Deserialize Entry handler", handler);
  138.             #endif
  139.             bFullDeserialization = false;
  140.             bMethodCall = false;
  141.             bMethodReturn = false;
  142.             TopObject = null;
  143.             topId = 0;
  144.             bIsCrossAppDomain = isCrossAppDomain;
  145.             bSimpleAssembly = (formatterEnums.FEassemblyFormat == FormatterAssemblyStyle.Simple);
  146.            
  147.             if (serParser == null)
  148.                 throw new ArgumentNullException("serParser", String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentNull_WithParamName"), serParser));
  149.            
  150.             if (fCheck) {
  151.                 try {
  152.                     CodeAccessPermission.DemandInternal(PermissionType.SecuritySerialization);
  153.                 }
  154.                 catch (Exception e) {
  155.                     deserializationSecurityException = e;
  156.                 }
  157.             }
  158.            
  159.             this.handler = handler;
  160.            
  161.            
  162.             if (bFullDeserialization) {
  163.                 // Reinitialize
  164.                 m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
  165.                 serObjectInfoInit = new SerObjectInfoInit();
  166.             }
  167.            
  168.             // Will call back to ParseObject, ParseHeader for each object found
  169.             serParser.Run();
  170.            
  171.             #if _DEBUG
  172.             SerTrace.Log(this, "Deserialize Finished Parsing DoFixups");
  173.             #endif
  174.            
  175.             if (bFullDeserialization)
  176.                 m_objectManager.DoFixups();
  177.            
  178.            
  179.             if (!bMethodCall && !bMethodReturn) {
  180.                 if (TopObject == null)
  181.                     throw new SerializationException(Environment.GetResourceString("Serialization_TopObject"));
  182.                
  183.                 //if TopObject has a surrogate then the actual object may be changed during special fixup
  184.                 //So refresh it using topID.
  185.                 if (HasSurrogate(TopObject.GetType()) && topId != 0)
  186.                     //Not yet resolved
  187.                     TopObject = m_objectManager.GetObject(topId);
  188.                
  189.                 if (TopObject is IObjectReference) {
  190.                     TopObject = ((IObjectReference)TopObject).GetRealObject(m_context);
  191.                 }
  192.             }
  193.            
  194.             SerTrace.Log(this, "Deserialize Exit ", TopObject);
  195.            
  196.             if (bFullDeserialization) {
  197.                 m_objectManager.RaiseDeserializationEvent();
  198.                 // This will raise both IDeserialization and [OnDeserialized] events
  199.             }
  200.            
  201.             // Return the headers if there is a handler
  202.             if (handler != null) {
  203.                 handlerObject = handler(headers);
  204.             }
  205.            
  206.             if (bMethodCall) {
  207.                 object[] methodCallArray = TopObject as object[];
  208.                 TopObject = binaryMethodCall.ReadArray(methodCallArray, handlerObject);
  209.             }
  210.             else if (bMethodReturn) {
  211.                 object[] methodReturnArray = TopObject as object[];
  212.                 TopObject = binaryMethodReturn.ReadArray(methodReturnArray, methodCallMessage, handlerObject);
  213.             }
  214.            
  215.             return TopObject;
  216.         }
  217.        
  218.         private bool HasSurrogate(Type t)
  219.         {
  220.             if (m_surrogates == null)
  221.                 return false;
  222.             ISurrogateSelector notUsed;
  223.             return m_surrogates.GetSurrogate(t, m_context, out notUsed) != null;
  224.         }
  225.        
  226.         private void CheckSerializable(Type t)
  227.         {
  228.             if (!t.IsSerializable && !HasSurrogate(t))
  229.                 throw new SerializationException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Serialization_NonSerType"), t.FullName, t.Assembly.FullName));
  230.         }
  231.        
  232.         private void InitFullDeserialization()
  233.         {
  234.             bFullDeserialization = true;
  235.             stack = new SerStack("ObjectReader Object Stack");
  236.            
  237.             m_objectManager = new ObjectManager(m_surrogates, m_context, false, bIsCrossAppDomain);
  238.             if (m_formatterConverter == null)
  239.                 m_formatterConverter = new FormatterConverter();
  240.         }
  241.        
  242.        
  243.         internal object CrossAppDomainArray(int index)
  244.         {
  245.             BCLDebug.Assert((index < crossAppDomainArray.Length), "[System.Runtime.Serialization.Formatters.BinaryObjectReader index out of range for CrossAppDomainArray]");
  246.             return crossAppDomainArray[index];
  247.         }
  248.        
  249.         internal ReadObjectInfo CreateReadObjectInfo(Type objectType)
  250.         {
  251.             return ReadObjectInfo.Create(objectType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
  252.         }
  253.        
  254.         internal ReadObjectInfo CreateReadObjectInfo(Type objectType, string[] memberNames, Type[] memberTypes)
  255.         {
  256.             return ReadObjectInfo.Create(objectType, memberNames, memberTypes, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
  257.         }
  258.        
  259.        
  260.         // Main Parse routine, called by the XML Parse Handlers in XMLParser and also called internally to
  261.         internal void Parse(ParseRecord pr)
  262.         {
  263.             #if _DEBUG
  264.             SerTrace.Log(this, "Parse");
  265.             stack.Dump();
  266.             pr.Dump();
  267.             #endif
  268.            
  269.             switch (pr.PRparseTypeEnum) {
  270.                 case InternalParseTypeE.SerializedStreamHeader:
  271.                     ParseSerializedStreamHeader(pr);
  272.                     break;
  273.                 case InternalParseTypeE.SerializedStreamHeaderEnd:
  274.                     ParseSerializedStreamHeaderEnd(pr);
  275.                     break;
  276.                 case InternalParseTypeE.Object:
  277.                     ParseObject(pr);
  278.                     break;
  279.                 case InternalParseTypeE.ObjectEnd:
  280.                     ParseObjectEnd(pr);
  281.                     break;
  282.                 case InternalParseTypeE.Member:
  283.                     ParseMember(pr);
  284.                     break;
  285.                 case InternalParseTypeE.MemberEnd:
  286.                     ParseMemberEnd(pr);
  287.                     break;
  288.                 case InternalParseTypeE.Body:
  289.                 case InternalParseTypeE.BodyEnd:
  290.                 case InternalParseTypeE.Envelope:
  291.                 case InternalParseTypeE.EnvelopeEnd:
  292.                     break;
  293.                 case InternalParseTypeE.Empty:
  294.                 default:
  295.                     throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_XMLElement"), pr.PRname));
  296.                     break;
  297.                
  298.             }
  299.         }
  300.        
  301.        
  302.         // Styled ParseError output
  303.         private void ParseError(ParseRecord processing, ParseRecord onStack)
  304.         {
  305.             #if _DEBUG
  306.             SerTrace.Log(this, " ParseError ", processing, " ", onStack);
  307.             #endif
  308.             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ParseError"), onStack.PRname + " " + ((Enum)onStack.PRparseTypeEnum) + " " + processing.PRname + " " + ((Enum)processing.PRparseTypeEnum)));
  309.         }
  310.        
  311.         // Parse the SerializedStreamHeader element. This is the first element in the stream if present
  312.         private void ParseSerializedStreamHeader(ParseRecord pr)
  313.         {
  314.             #if _DEBUG
  315.             SerTrace.Log(this, "SerializedHeader ", pr);
  316.             #endif
  317.             stack.Push(pr);
  318.         }
  319.        
  320.         // Parse the SerializedStreamHeader end element. This is the last element in the stream if present
  321.         private void ParseSerializedStreamHeaderEnd(ParseRecord pr)
  322.         {
  323.             #if _DEBUG
  324.             SerTrace.Log(this, "SerializedHeaderEnd ", pr);
  325.             #endif
  326.             stack.Pop();
  327.         }
  328.        
  329.         private bool IsRemoting {
  330. //return (m_context.State & (StreamingContextStates.Persistence|StreamingContextStates.File|StreamingContextStates.Clone)) == 0;
  331.             get { return (bMethodCall || bMethodReturn); }
  332.         }
  333.        
  334.         internal void CheckSecurity(ParseRecord pr)
  335.         {
  336.             InternalST.SoapAssert(pr != null, "[BinaryObjectReader.CheckSecurity]pr!=null");
  337.             Type t = pr.PRdtType;
  338.             if (t != null) {
  339.                 if (IsRemoting) {
  340.                     if (typeof(MarshalByRefObject).IsAssignableFrom(t))
  341.                         throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_MBRAsMBV"), t.FullName));
  342.                     FormatterServices.CheckTypeSecurity(t, formatterEnums.FEsecurityLevel);
  343.                 }
  344.             }
  345.            
  346.             //If we passed the security check, they can do whatever they'd like,
  347.             //so we'll just short-circuit this.
  348.             if (deserializationSecurityException == null) {
  349.                 return;
  350.             }
  351.            
  352.             // BaseTypes and Array of basetypes allowed
  353.            
  354.             if (t != null) {
  355.                 if (t.IsPrimitive || t == Converter.typeofString)
  356.                     return;
  357.                
  358.                 if (typeof(Enum).IsAssignableFrom(t))
  359.                     return;
  360.                
  361.                 if (t.IsArray) {
  362.                     Type type = t.GetElementType();
  363.                     if (type.IsPrimitive || type == Converter.typeofString)
  364.                         return;
  365.                 }
  366.             }
  367.            
  368.             throw deserializationSecurityException;
  369.         }
  370.        
  371.         // New object encountered in stream
  372.         private void ParseObject(ParseRecord pr)
  373.         {
  374.             #if _DEBUG
  375.             SerTrace.Log(this, "ParseObject Entry ");
  376.             #endif
  377.            
  378.             if (!bFullDeserialization)
  379.                 InitFullDeserialization();
  380.            
  381.             if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top)
  382.                 topId = pr.PRobjectId;
  383.            
  384.             if (pr.PRparseTypeEnum == InternalParseTypeE.Object) {
  385.                 stack.Push(pr);
  386.                 // Nested objects member names are already on stack
  387.             }
  388.            
  389.             if (pr.PRobjectTypeEnum == InternalObjectTypeE.Array) {
  390.                 ParseArray(pr);
  391.                 #if _DEBUG
  392.                 SerTrace.Log(this, "ParseObject Exit, ParseArray ");
  393.                 #endif
  394.                 return;
  395.             }
  396.            
  397.             // If the Type is null, this means we have a typeload issue
  398.             // mark the object with TypeLoadExceptionHolder
  399.             if (pr.PRdtType == null) {
  400.                 pr.PRnewObj = new TypeLoadExceptionHolder(pr.PRkeyDt);
  401.                 return;
  402.             }
  403.            
  404.             if (pr.PRdtType == Converter.typeofString) {
  405.                 // String as a top level object
  406.                 if (pr.PRvalue != null) {
  407.                     pr.PRnewObj = pr.PRvalue;
  408.                     if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  409.                         #if _DEBUG
  410.                         SerTrace.Log(this, "ParseObject String as top level, Top Object Resolved");
  411.                         #endif
  412.                         TopObject = pr.PRnewObj;
  413.                         //stack.Pop();
  414.                         return;
  415.                     }
  416.                     else {
  417.                         #if _DEBUG
  418.                         SerTrace.Log(this, "ParseObject String as an object");
  419.                         #endif
  420.                         stack.Pop();
  421.                         RegisterObject(pr.PRnewObj, pr, (ParseRecord)stack.Peek());
  422.                         return;
  423.                     }
  424.                 }
  425.                 else {
  426.                     // xml Doesn't have the value until later
  427.                     return;
  428.                 }
  429.             }
  430.             else {
  431.                 CheckSerializable(pr.PRdtType);
  432.                 if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
  433.                     pr.PRnewObj = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);
  434.                 else
  435.                     pr.PRnewObj = FormatterServices.GetUninitializedObject(pr.PRdtType);
  436.                
  437.                 // Run the OnDeserializing methods
  438.                 m_objectManager.RaiseOnDeserializingEvent(pr.PRnewObj);
  439.             }
  440.            
  441.             if (pr.PRnewObj == null)
  442.                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_TopObjectInstantiate"), pr.PRdtType));
  443.            
  444.             if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  445.                 #if _DEBUG
  446.                 SerTrace.Log(this, "ParseObject Top Object Resolved ", pr.PRnewObj.GetType());
  447.                 #endif
  448.                 TopObject = pr.PRnewObj;
  449.             }
  450.            
  451.             if (pr.PRobjectInfo == null)
  452.                 pr.PRobjectInfo = ReadObjectInfo.Create(pr.PRdtType, m_surrogates, m_context, m_objectManager, serObjectInfoInit, m_formatterConverter, bSimpleAssembly);
  453.            
  454.             CheckSecurity(pr);
  455.            
  456.             #if _DEBUG
  457.             SerTrace.Log(this, "ParseObject Exit ");
  458.             #endif
  459.         }
  460.        
  461.         // End of object encountered in stream
  462.         private void ParseObjectEnd(ParseRecord pr)
  463.         {
  464.             #if _DEBUG
  465.             SerTrace.Log(this, "ParseObjectEnd Entry ", pr.Trace());
  466.             #endif
  467.             ParseRecord objectPr = (ParseRecord)stack.Peek();
  468.             if (objectPr == null)
  469.                 objectPr = pr;
  470.            
  471.             //BCLDebug.Assert(objectPr != null, "[System.Runtime.Serialization.Formatters.ParseObjectEnd]objectPr != null");
  472.            
  473.             #if _DEBUG
  474.             SerTrace.Log(this, "ParseObjectEnd objectPr ", objectPr.Trace());
  475.             #endif
  476.            
  477.             if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  478.                 #if _DEBUG
  479.                 SerTrace.Log(this, "ParseObjectEnd Top Object dtType ", objectPr.PRdtType);
  480.                 #endif
  481.                 if (objectPr.PRdtType == Converter.typeofString) {
  482.                     #if _DEBUG
  483.                     SerTrace.Log(this, "ParseObjectEnd Top String");
  484.                     #endif
  485.                     objectPr.PRnewObj = objectPr.PRvalue;
  486.                     TopObject = objectPr.PRnewObj;
  487.                     return;
  488.                 }
  489.             }
  490.            
  491.             stack.Pop();
  492.             ParseRecord parentPr = (ParseRecord)stack.Peek();
  493.            
  494.             if (objectPr.PRnewObj == null)
  495.                 return;
  496.            
  497.             if (objectPr.PRobjectTypeEnum == InternalObjectTypeE.Array) {
  498.                 if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  499.                     #if _DEBUG
  500.                     SerTrace.Log(this, "ParseObjectEnd Top Object (Array) Resolved");
  501.                     #endif
  502.                     TopObject = objectPr.PRnewObj;
  503.                 }
  504.                
  505.                 #if _DEBUG
  506.                 SerTrace.Log(this, "ParseArray RegisterObject ", objectPr.PRobjectId, " ", objectPr.PRnewObj.GetType());
  507.                 #endif
  508.                 RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
  509.                
  510.                 return;
  511.             }
  512.            
  513.             objectPr.PRobjectInfo.PopulateObjectMembers(objectPr.PRnewObj, objectPr.PRmemberData);
  514.            
  515.             // Registration is after object is populated
  516.             if ((!objectPr.PRisRegistered) && (objectPr.PRobjectId > 0)) {
  517.                 #if _DEBUG
  518.                 SerTrace.Log(this, "ParseObject Register Object ", objectPr.PRobjectId, " ", objectPr.PRnewObj.GetType());
  519.                 #endif
  520.                 RegisterObject(objectPr.PRnewObj, objectPr, parentPr);
  521.             }
  522.            
  523.             if (objectPr.PRisValueTypeFixup) {
  524.                 #if _DEBUG
  525.                 SerTrace.Log(this, "ParseObjectEnd ValueTypeFixup ", objectPr.PRnewObj.GetType());
  526.                 #endif
  527.                 ValueFixup fixup = (ValueFixup)ValueFixupStack.Pop();
  528.                 //Value fixup
  529.                 fixup.Fixup(objectPr, parentPr);
  530.                 // Value fixup
  531.             }
  532.            
  533.             if (objectPr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  534.                 #if _DEBUG
  535.                 SerTrace.Log(this, "ParseObjectEnd Top Object Resolved ", objectPr.PRnewObj.GetType());
  536.                 #endif
  537.                 TopObject = objectPr.PRnewObj;
  538.             }
  539.            
  540.             objectPr.PRobjectInfo.ObjectEnd();
  541.            
  542.             #if _DEBUG
  543.             SerTrace.Log(this, "ParseObjectEnd Exit ", objectPr.PRnewObj.GetType(), " id: ", objectPr.PRobjectId);
  544.             #endif
  545.         }
  546.        
  547.        
  548.        
  549.         // Array object encountered in stream
  550.         private void ParseArray(ParseRecord pr)
  551.         {
  552.             SerTrace.Log(this, "ParseArray Entry");
  553.            
  554.             long genId = pr.PRobjectId;
  555.            
  556.             if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) {
  557.                 SerTrace.Log(this, "ParseArray bin.base64 ", pr.PRvalue.Length, " ", pr.PRvalue);
  558.                 // ByteArray
  559.                 if (pr.PRvalue.Length > 0)
  560.                     pr.PRnewObj = Convert.FromBase64String(pr.PRvalue);
  561.                 else
  562.                     pr.PRnewObj = new byte[0];
  563.                
  564.                 if (stack.Peek() == pr) {
  565.                     SerTrace.Log(this, "ParseArray, bin.base64 has been stacked");
  566.                     stack.Pop();
  567.                 }
  568.                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  569.                     TopObject = pr.PRnewObj;
  570.                 }
  571.                
  572.                 ParseRecord parentPr = (ParseRecord)stack.Peek();
  573.                
  574.                 // Base64 can be registered at this point because it is populated
  575.                 SerTrace.Log(this, "ParseArray RegisterObject ", pr.PRobjectId, " ", pr.PRnewObj.GetType());
  576.                 RegisterObject(pr.PRnewObj, pr, parentPr);
  577.                
  578.             }
  579.             else if ((pr.PRnewObj != null) && Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode)) {
  580.                 // Primtive typed Array has already been read
  581.                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Top) {
  582.                     TopObject = pr.PRnewObj;
  583.                 }
  584.                
  585.                 ParseRecord parentPr = (ParseRecord)stack.Peek();
  586.                
  587.                 // Primitive typed array can be registered at this point because it is populated
  588.                 SerTrace.Log(this, "ParseArray RegisterObject ", pr.PRobjectId, " ", pr.PRnewObj.GetType());
  589.                 RegisterObject(pr.PRnewObj, pr, parentPr);
  590.             }
  591.             else if ((pr.PRarrayTypeEnum == InternalArrayTypeE.Jagged) || (pr.PRarrayTypeEnum == InternalArrayTypeE.Single)) {
  592.                 // Multidimensional jagged array or single array
  593.                 SerTrace.Log(this, "ParseArray Before Jagged,Simple create ", pr.PRarrayElementType, " ", pr.PRlengthA[0]);
  594.                 bool bCouldBeValueType = true;
  595.                 if ((pr.PRlowerBoundA == null) || (pr.PRlowerBoundA[0] == 0)) {
  596.                     if (pr.PRarrayElementType == Converter.typeofString) {
  597.                         pr.PRobjectA = new string[pr.PRlengthA[0]];
  598.                         pr.PRnewObj = pr.PRobjectA;
  599.                         bCouldBeValueType = false;
  600.                     }
  601.                     else if (pr.PRarrayElementType == Converter.typeofObject) {
  602.                         pr.PRobjectA = new object[pr.PRlengthA[0]];
  603.                         pr.PRnewObj = pr.PRobjectA;
  604.                         bCouldBeValueType = false;
  605.                     }
  606.                     else if (pr.PRarrayElementType != null) {
  607.                         pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA[0]);
  608.                     }
  609.                     pr.PRisLowerBound = false;
  610.                 }
  611.                 else {
  612.                     if (pr.PRarrayElementType != null) {
  613.                         pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
  614.                     }
  615.                     pr.PRisLowerBound = true;
  616.                 }
  617.                
  618.                 if (pr.PRarrayTypeEnum == InternalArrayTypeE.Single) {
  619.                     if (!pr.PRisLowerBound && (Converter.IsWriteAsByteArray(pr.PRarrayElementTypeCode))) {
  620.                         pr.PRprimitiveArray = new PrimitiveArray(pr.PRarrayElementTypeCode, (Array)pr.PRnewObj);
  621.                     }
  622.                     else if (bCouldBeValueType && pr.PRarrayElementType != null) {
  623.                         if (!pr.PRarrayElementType.IsValueType && !pr.PRisLowerBound)
  624.                             pr.PRobjectA = (object[])pr.PRnewObj;
  625.                     }
  626.                 }
  627.                
  628.                 SerTrace.Log(this, "ParseArray Jagged,Simple Array ", pr.PRnewObj.GetType());
  629.                
  630.                 // For binary, headers comes in as an array of header objects
  631.                 if (pr.PRobjectPositionEnum == InternalObjectPositionE.Headers) {
  632.                     SerTrace.Log(this, "ParseArray header array");
  633.                     headers = (Header[])pr.PRnewObj;
  634.                 }
  635.                
  636.                 pr.PRindexMap = new int[1];
  637.                
  638.             }
  639.             else if (pr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular) {
  640.                 // Rectangle array
  641.                
  642.                 pr.PRisLowerBound = false;
  643.                 if (pr.PRlowerBoundA != null) {
  644.                     for (int i = 0; i < pr.PRrank; i++) {
  645.                         if (pr.PRlowerBoundA[i] != 0)
  646.                             pr.PRisLowerBound = true;
  647.                     }
  648.                 }
  649.                
  650.                 if (pr.PRarrayElementType != null) {
  651.                     if (!pr.PRisLowerBound)
  652.                         pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA);
  653.                     else
  654.                         pr.PRnewObj = Array.CreateInstance(pr.PRarrayElementType, pr.PRlengthA, pr.PRlowerBoundA);
  655.                 }
  656.                
  657.                 SerTrace.Log(this, "ParseArray Rectangle Array ", pr.PRnewObj.GetType(), " lower Bound ", pr.PRisLowerBound);
  658.                
  659.                 // Calculate number of items
  660.                 int sum = 1;
  661.                 for (int i = 0; i < pr.PRrank; i++) {
  662.                     sum = sum * pr.PRlengthA[i];
  663.                 }
  664.                 pr.PRindexMap = new int[pr.PRrank];
  665.                 pr.PRrectangularMap = new int[pr.PRrank];
  666.                 pr.PRlinearlength = sum;
  667.             }
  668.             else
  669.                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_ArrayType"), ((Enum)pr.PRarrayTypeEnum)));
  670.            
  671.             CheckSecurity(pr);
  672.             SerTrace.Log(this, "ParseArray Exit");
  673.         }
  674.        
  675.        
  676.         // Builds a map for each item in an incoming rectangle array. The map specifies where the item is placed in the output Array Object
  677.        
  678.         private void NextRectangleMap(ParseRecord pr)
  679.         {
  680.             // For each invocation, calculate the next rectangular array position
  681.             // example
  682.             // indexMap 0 [0,0,0]
  683.             // indexMap 1 [0,0,1]
  684.             // indexMap 2 [0,0,2]
  685.             // indexMap 3 [0,0,3]
  686.             // indexMap 4 [0,1,0]
  687.             for (int irank = pr.PRrank - 1; irank > -1; irank--) {
  688.                 // Find the current or lower dimension which can be incremented.
  689.                 if (pr.PRrectangularMap[irank] < pr.PRlengthA[irank] - 1) {
  690.                     // The current dimension is at maximum. Increase the next lower dimension by 1
  691.                     pr.PRrectangularMap[irank]++;
  692.                     if (irank < pr.PRrank - 1) {
  693.                         // The current dimension and higher dimensions are zeroed.
  694.                         for (int i = irank + 1; i < pr.PRrank; i++)
  695.                             pr.PRrectangularMap[i] = 0;
  696.                     }
  697.                     Array.Copy(pr.PRrectangularMap, pr.PRindexMap, pr.PRrank);
  698.                     break;
  699.                 }
  700.                
  701.             }
  702.         }
  703.        
  704.        
  705.         // Array object item encountered in stream
  706.         private void ParseArrayMember(ParseRecord pr)
  707.         {
  708.             SerTrace.Log(this, "ParseArrayMember Entry");
  709.             ParseRecord objectPr = (ParseRecord)stack.Peek();
  710.            
  711.            
  712.             // Set up for inserting value into correct array position
  713.             if (objectPr.PRarrayTypeEnum == InternalArrayTypeE.Rectangular) {
  714.                
  715.                 if (objectPr.PRmemberIndex > 0)
  716.                     NextRectangleMap(objectPr);
  717.                 // Rectangle array, calculate position in array
  718.                 if (objectPr.PRisLowerBound) {
  719.                     for (int i = 0; i < objectPr.PRrank; i++) {
  720.                         objectPr.PRindexMap[i] = objectPr.PRrectangularMap[i] + objectPr.PRlowerBoundA[i];
  721.                     }
  722.                 }
  723.             }
  724.             else {
  725.                 if (!objectPr.PRisLowerBound) {
  726.                     objectPr.PRindexMap[0] = objectPr.PRmemberIndex;
  727.                     // Zero based array
  728.                 }
  729.                 else
  730.                     objectPr.PRindexMap[0] = objectPr.PRlowerBoundA[0] + objectPr.PRmemberIndex;
  731.                 // Lower Bound based array
  732.             }
  733.             IndexTraceMessage("ParseArrayMember isLowerBound " + objectPr.PRisLowerBound + " indexMap ", objectPr.PRindexMap);
  734.            
  735.             // Set Array element according to type of element
  736.            
  737.             if (pr.PRmemberValueEnum == InternalMemberValueE.Reference) {
  738.                 // Object Reference
  739.                
  740.                 // See if object has already been instantiated
  741.                 object refObj = m_objectManager.GetObject(pr.PRidRef);
  742.                 if (refObj == null) {
  743.                     // Object not instantiated
  744.                     // Array fixup manager
  745.                     IndexTraceMessage("ParseArrayMember Record Fixup " + objectPr.PRnewObj.GetType(), objectPr.PRindexMap);
  746.                     int[] fixupIndex = new int[objectPr.PRrank];
  747.                     Array.Copy(objectPr.PRindexMap, 0, fixupIndex, 0, objectPr.PRrank);
  748.                    
  749.                     SerTrace.Log(this, "ParseArrayMember RecordArrayElementFixup objectId ", objectPr.PRobjectId, " idRef ", pr.PRidRef);
  750.                     m_objectManager.RecordArrayElementFixup(objectPr.PRobjectId, fixupIndex, pr.PRidRef);
  751.                 }
  752.                 else {
  753.                     IndexTraceMessage("ParseArrayMember SetValue ObjectReference " + objectPr.PRnewObj.GetType() + " " + refObj, objectPr.PRindexMap);
  754.                     if (objectPr.PRobjectA != null)
  755.                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = refObj;
  756.                     else
  757.                         ((Array)objectPr.PRnewObj).SetValue(refObj, objectPr.PRindexMap);
  758.                     // Object has been instantiated
  759.                 }
  760.             }
  761.             else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested) {
  762.                 //Set up dtType for ParseObject
  763.                 SerTrace.Log(this, "ParseArrayMember Nested ");
  764.                 if (pr.PRdtType == null) {
  765.                     pr.PRdtType = objectPr.PRarrayElementType;
  766.                 }
  767.                
  768.                 ParseObject(pr);
  769.                 stack.Push(pr);
  770.                
  771.                 if (objectPr.PRarrayElementType != null) {
  772.                     if ((objectPr.PRarrayElementType.IsValueType) && (pr.PRarrayElementTypeCode == InternalPrimitiveTypeE.Invalid)) {
  773.                         #if _DEBUG
  774.                         SerTrace.Log("ParseArrayMember ValueType ObjectPr ", objectPr.PRnewObj, " index ", objectPr.PRmemberIndex);
  775.                         #endif
  776.                         pr.PRisValueTypeFixup = true;
  777.                         //Valuefixup
  778.                         ValueFixupStack.Push(new ValueFixup((Array)objectPr.PRnewObj, objectPr.PRindexMap));
  779.                         //valuefixup
  780.                     }
  781.                     else {
  782.                         #if _DEBUG
  783.                         SerTrace.Log("ParseArrayMember SetValue Nested, memberIndex ", objectPr.PRmemberIndex);
  784.                         IndexTraceMessage("ParseArrayMember SetValue Nested ContainerObject " + objectPr.PRnewObj.GetType() + " " + objectPr.PRnewObj + " item Object " + pr.PRnewObj + " index ", objectPr.PRindexMap);
  785.                        
  786.                         stack.Dump();
  787.                         SerTrace.Log("ParseArrayMember SetValue Nested ContainerObject objectPr ", objectPr.Trace());
  788.                         SerTrace.Log("ParseArrayMember SetValue Nested ContainerObject pr ", pr.Trace());
  789.                         #endif
  790.                         if (objectPr.PRobjectA != null)
  791.                             objectPr.PRobjectA[objectPr.PRindexMap[0]] = pr.PRnewObj;
  792.                         else
  793.                             ((Array)objectPr.PRnewObj).SetValue(pr.PRnewObj, objectPr.PRindexMap);
  794.                     }
  795.                 }
  796.             }
  797.             else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue) {
  798.                 if ((objectPr.PRarrayElementType == Converter.typeofString) || (pr.PRdtType == Converter.typeofString)) {
  799.                     // String in either a string array, or a string element of an object array
  800.                     ParseString(pr, objectPr);
  801.                     IndexTraceMessage("ParseArrayMember SetValue String " + objectPr.PRnewObj.GetType() + " " + pr.PRvalue, objectPr.PRindexMap);
  802.                     if (objectPr.PRobjectA != null)
  803.                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = (object)pr.PRvalue;
  804.                     else
  805.                         ((Array)objectPr.PRnewObj).SetValue((object)pr.PRvalue, objectPr.PRindexMap);
  806.                 }
  807.                 else if (objectPr.PRisArrayVariant) {
  808.                     // Array of type object
  809.                     if (pr.PRkeyDt == null)
  810.                         throw new SerializationException(Environment.GetResourceString("Serialization_ArrayTypeObject"));
  811.                    
  812.                     object var = null;
  813.                    
  814.                     if (pr.PRdtType == Converter.typeofString) {
  815.                         ParseString(pr, objectPr);
  816.                         var = pr.PRvalue;
  817.                     }
  818.                     else if (pr.PRdtTypeCode == InternalPrimitiveTypeE.Invalid) {
  819.                         CheckSerializable(pr.PRdtType);
  820.                         // Not nested and invalid, so it is an empty object
  821.                         if (IsRemoting && formatterEnums.FEsecurityLevel != TypeFilterLevel.Full)
  822.                             var = FormatterServices.GetSafeUninitializedObject(pr.PRdtType);
  823.                         else
  824.                             var = FormatterServices.GetUninitializedObject(pr.PRdtType);
  825.                     }
  826.                     else {
  827.                         if (pr.PRvarValue != null)
  828.                             var = pr.PRvarValue;
  829.                         else
  830.                             var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
  831.                     }
  832.                     IndexTraceMessage("ParseArrayMember SetValue variant or Object " + objectPr.PRnewObj.GetType() + " var " + var + " indexMap ", objectPr.PRindexMap);
  833.                     if (objectPr.PRobjectA != null)
  834.                         objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
  835.                     else
  836.                         ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap);
  837.                     // Primitive type
  838.                 }
  839.                 else {
  840.                     // Primitive type
  841.                     if (objectPr.PRprimitiveArray != null) {
  842.                         // Fast path for Soap primitive arrays. Binary was handled in the BinaryParser
  843.                         objectPr.PRprimitiveArray.SetValue(pr.PRvalue, objectPr.PRindexMap[0]);
  844.                     }
  845.                     else {
  846.                        
  847.                         object var = null;
  848.                         if (pr.PRvarValue != null)
  849.                             var = pr.PRvarValue;
  850.                         else
  851.                             var = Converter.FromString(pr.PRvalue, objectPr.PRarrayElementTypeCode);
  852.                         SerTrace.Log(this, "ParseArrayMember SetValue Primitive pr.PRvalue " + var, " elementTypeCode ", ((Enum)objectPr.PRdtTypeCode));
  853.                         IndexTraceMessage("ParseArrayMember SetValue Primitive " + objectPr.PRnewObj.GetType() + " var: " + var + " varType " + var.GetType(), objectPr.PRindexMap);
  854.                         if (objectPr.PRobjectA != null) {
  855.                             SerTrace.Log(this, "ParseArrayMember SetValue Primitive predefined array " + objectPr.PRobjectA.GetType());
  856.                             objectPr.PRobjectA[objectPr.PRindexMap[0]] = var;
  857.                         }
  858.                         else
  859.                             ((Array)objectPr.PRnewObj).SetValue(var, objectPr.PRindexMap);
  860.                         // Primitive type
  861.                         SerTrace.Log(this, "ParseArrayMember SetValue Primitive after");
  862.                     }
  863.                 }
  864.             }
  865.             else if (pr.PRmemberValueEnum == InternalMemberValueE.Null) {
  866.                 SerTrace.Log("ParseArrayMember Null item ", pr.PRmemberIndex, " nullCount ", pr.PRnullCount);
  867.                 objectPr.PRmemberIndex += pr.PRnullCount - 1;
  868.                 //also incremented again below
  869.             }
  870.             else
  871.                 ParseError(pr, objectPr);
  872.            
  873.             #if _DEBUG
  874.             SerTrace.Log("ParseArrayMember increment memberIndex ", objectPr.PRmemberIndex, " ", objectPr.Trace());
  875.             #endif
  876.             objectPr.PRmemberIndex++;
  877.             SerTrace.Log("ParseArrayMember Exit");
  878.         }
  879.        
  880.         private void ParseArrayMemberEnd(ParseRecord pr)
  881.         {
  882.             SerTrace.Log(this, "ParseArrayMemberEnd");
  883.             // If this is a nested array object, then pop the stack
  884.             if (pr.PRmemberValueEnum == InternalMemberValueE.Nested) {
  885.                 ParseObjectEnd(pr);
  886.             }
  887.         }
  888.        
  889.        
  890.         // Object member encountered in stream
  891.         private void ParseMember(ParseRecord pr)
  892.         {
  893.             SerTrace.Log(this, "ParseMember Entry ");
  894.            
  895.            
  896.             ParseRecord objectPr = (ParseRecord)stack.Peek();
  897.             string objName = null;
  898.             if (objectPr != null)
  899.                 objName = objectPr.PRname;
  900.            
  901.             #if _DEBUG
  902.             SerTrace.Log(this, "ParseMember ", objectPr.PRobjectId, " ", pr.PRname);
  903.             SerTrace.Log(this, "ParseMember objectPr ", objectPr.Trace());
  904.             SerTrace.Log(this, "ParseMember pr ", pr.Trace());
  905.             #endif
  906.             switch (pr.PRmemberTypeEnum) {
  907.                 case InternalMemberTypeE.Item:
  908.                     ParseArrayMember(pr);
  909.                     return;
  910.                 case InternalMemberTypeE.Field:
  911.                     break;
  912.             }
  913.            
  914.            
  915.             //if ((pr.PRdtType == null) && !objectPr.PRobjectInfo.isSi)
  916.             if ((pr.PRdtType == null) && objectPr.PRobjectInfo.isTyped) {
  917.                 SerTrace.Log(this, "ParseMember pr.PRdtType null and not isSi");
  918.                 pr.PRdtType = objectPr.PRobjectInfo.GetType(pr.PRname);
  919.                
  920.                 if (pr.PRdtType != null)
  921.                     pr.PRdtTypeCode = Converter.ToCode(pr.PRdtType);
  922.             }
  923.            
  924.             if (pr.PRmemberValueEnum == InternalMemberValueE.Null) {
  925.                 // Value is Null
  926.                 SerTrace.Log(this, "ParseMember null member: ", pr.PRname);
  927.                 SerTrace.Log(this, "AddValue 1");
  928.                 objectPr.PRobjectInfo.AddValue(pr.PRname, null, ref objectPr.PRsi, ref objectPr.PRmemberData);
  929.             }
  930.             else if (pr.PRmemberValueEnum == InternalMemberValueE.Nested) {
  931.                 SerTrace.Log(this, "ParseMember Nested Type member: ", pr.PRname, " objectPr.PRnewObj ", objectPr.PRnewObj);
  932.                 ParseObject(pr);
  933.                 stack.Push(pr);
  934.                 SerTrace.Log(this, "AddValue 2 ", pr.PRnewObj, " is value type ", pr.PRnewObj.GetType().IsValueType);
  935.                
  936.                 if ((pr.PRobjectInfo != null) && (pr.PRobjectInfo.objectType != null) && (pr.PRobjectInfo.objectType.IsValueType)) {
  937.                     SerTrace.Log("ParseMember ValueType ObjectPr ", objectPr.PRnewObj, " memberName ", pr.PRname, " nested object ", pr.PRnewObj);
  938.                     pr.PRisValueTypeFixup = true;
  939.                     //Valuefixup
  940.                     ValueFixupStack.Push(new ValueFixup(objectPr.PRnewObj, pr.PRname, objectPr.PRobjectInfo));
  941.                     //valuefixup
  942.                 }
  943.                 else {
  944.                     SerTrace.Log(this, "AddValue 2A ");
  945.                     objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRnewObj, ref objectPr.PRsi, ref objectPr.PRmemberData);
  946.                 }
  947.             }
  948.             else if (pr.PRmemberValueEnum == InternalMemberValueE.Reference) {
  949.                 SerTrace.Log(this, "ParseMember Reference Type member: ", pr.PRname);
  950.                 // See if object has already been instantiated
  951.                 object refObj = m_objectManager.GetObject(pr.PRidRef);
  952.                 if (refObj == null) {
  953.                     SerTrace.Log(this, "ParseMember RecordFixup: ", pr.PRname);
  954.                     SerTrace.Log(this, "AddValue 3");
  955.                     objectPr.PRobjectInfo.AddValue(pr.PRname, null, ref objectPr.PRsi, ref objectPr.PRmemberData);
  956.                     objectPr.PRobjectInfo.RecordFixup(objectPr.PRobjectId, pr.PRname, pr.PRidRef);
  957.                     // Object not instantiated
  958.                 }
  959.                 else {
  960.                     SerTrace.Log(this, "ParseMember Referenced Object Known ", pr.PRname, " ", refObj);
  961.                     SerTrace.Log(this, "AddValue 5");
  962.                     objectPr.PRobjectInfo.AddValue(pr.PRname, refObj, ref objectPr.PRsi, ref objectPr.PRmemberData);
  963.                 }
  964.             }
  965.            
  966.             else if (pr.PRmemberValueEnum == InternalMemberValueE.InlineValue) {
  967.                 // Primitive type or String
  968.                 SerTrace.Log(this, "ParseMember primitive or String member: ", pr.PRname);
  969.                
  970.                 if (pr.PRdtType == Converter.typeofString) {
  971.                     ParseString(pr, objectPr);
  972.                     SerTrace.Log(this, "AddValue 6");
  973.                     objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue, ref objectPr.PRsi, ref objectPr.PRmemberData);
  974.                 }
  975.                 else if (pr.PRdtTypeCode == InternalPrimitiveTypeE.Invalid) {
  976.                     // The member field was an object put the value is Inline either bin.Base64 or invalid
  977.                     if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) {
  978.                         SerTrace.Log(this, "AddValue 7");
  979.                         objectPr.PRobjectInfo.AddValue(pr.PRname, Convert.FromBase64String(pr.PRvalue), ref objectPr.PRsi, ref objectPr.PRmemberData);
  980.                     }
  981.                     else if (pr.PRdtType == Converter.typeofObject)
  982.                         throw new SerializationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Serialization_TypeMissing"), pr.PRname));
  983.                     else {
  984.                         SerTrace.Log(this, "Object Class with no memberInfo data Member " + pr.PRname + " type " + pr.PRdtType);
  985.                        
  986.                         ParseString(pr, objectPr);
  987.                         // Register the object if it has an objectId
  988.                         // Object Class with no memberInfo data
  989.                         // only special case where AddValue is needed?
  990.                         if (pr.PRdtType == Converter.typeofSystemVoid) {
  991.                             SerTrace.Log(this, "AddValue 9");
  992.                             objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRdtType, ref objectPr.PRsi, ref objectPr.PRmemberData);
  993.                         }
  994.                         else if (objectPr.PRobjectInfo.isSi) {
  995.                             // ISerializable are added as strings, the conversion to type is done by the
  996.                             // ISerializable object
  997.                             SerTrace.Log(this, "AddValue 10");
  998.                             objectPr.PRobjectInfo.AddValue(pr.PRname, pr.PRvalue, ref objectPr.PRsi, ref objectPr.PRmemberData);
  999.                         }
  1000.                     }
  1001.                 }
  1002.                 else {
  1003.                     object var = null;
  1004.                     if (pr.PRvarValue != null)
  1005.                         var = pr.PRvarValue;
  1006.                     else
  1007.                         var = Converter.FromString(pr.PRvalue, pr.PRdtTypeCode);
  1008.                     #if _DEBUG
  1009.                     // Not a string, convert the value
  1010.                     SerTrace.Log(this, "ParseMember Converting primitive and storing");
  1011.                     stack.Dump();
  1012.                     SerTrace.Log(this, "ParseMember pr " + pr.Trace());
  1013.                     SerTrace.Log(this, "ParseMember objectPr ", objectPr.Trace());
  1014.                    
  1015.                     SerTrace.Log(this, "AddValue 11");
  1016.                     #endif
  1017.                     objectPr.PRobjectInfo.AddValue(pr.PRname, var, ref objectPr.PRsi, ref objectPr.PRmemberData);
  1018.                 }
  1019.             }
  1020.             else
  1021.                 ParseError(pr, objectPr);
  1022.         }
  1023.        
  1024.         // Object member end encountered in stream
  1025.         private void ParseMemberEnd(ParseRecord pr)
  1026.         {
  1027.             SerTrace.Log(this, "ParseMemberEnd");
  1028.             switch (pr.PRmemberTypeEnum) {
  1029.                 case InternalMemberTypeE.Item:
  1030.                     ParseArrayMemberEnd(pr);
  1031.                     return;
  1032.                 case InternalMemberTypeE.Field:
  1033.                     if (pr.PRmemberValueEnum == InternalMemberValueE.Nested)
  1034.                         ParseObjectEnd(pr);
  1035.                     break;
  1036.                 default:
  1037.                     ParseError(pr, (ParseRecord)stack.Peek());
  1038.                     break;
  1039.             }
  1040.         }
  1041.        
  1042.         // Processes a string object by getting an internal ID for it and registering it with the objectManager
  1043.         private void ParseString(ParseRecord pr, ParseRecord parentPr)
  1044.         {
  1045.             SerTrace.Log(this, "ParseString Entry ", pr.PRobjectId, " ", pr.PRvalue, " ", pr.PRisRegistered);
  1046.             // Process String class
  1047.             if ((!pr.PRisRegistered) && (pr.PRobjectId > 0)) {
  1048.                 SerTrace.Log(this, "ParseString RegisterObject ", pr.PRvalue, " ", pr.PRobjectId);
  1049.                 // String is treated as an object if it has an id
  1050.                 //m_objectManager.RegisterObject(pr.PRvalue, pr.PRobjectId);
  1051.                 RegisterObject(pr.PRvalue, pr, parentPr, true);
  1052.             }
  1053.         }
  1054.        
  1055.        
  1056.         private void RegisterObject(object obj, ParseRecord pr, ParseRecord objectPr)
  1057.         {
  1058.             RegisterObject(obj, pr, objectPr, false);
  1059.         }
  1060.        
  1061.         private void RegisterObject(object obj, ParseRecord pr, ParseRecord objectPr, bool bIsString)
  1062.         {
  1063.             if (!pr.PRisRegistered) {
  1064.                 pr.PRisRegistered = true;
  1065.                
  1066.                 SerializationInfo si = null;
  1067.                 long parentId = 0;
  1068.                 MemberInfo memberInfo = null;
  1069.                 int[] indexMap = null;
  1070.                
  1071.                 if (objectPr != null) {
  1072.                     indexMap = objectPr.PRindexMap;
  1073.                     parentId = objectPr.PRobjectId;
  1074.                    
  1075.                     if (objectPr.PRobjectInfo != null) {
  1076.                         if (!objectPr.PRobjectInfo.isSi) {
  1077.                             // ParentId is only used if there is a memberInfo
  1078.                            
  1079.                             memberInfo = objectPr.PRobjectInfo.GetMemberInfo(pr.PRname);
  1080.                         }
  1081.                     }
  1082.                 }
  1083.                 // SerializationInfo is always needed for ISerialization
  1084.                 si = pr.PRsi;
  1085.                
  1086.                 SerTrace.Log(this, "RegisterObject 0bj ", obj, " objectId ", pr.PRobjectId, " si ", si, " parentId ", parentId, " memberInfo ",
  1087.                 memberInfo, " indexMap " + indexMap);
  1088.                 if (bIsString)
  1089.                     m_objectManager.RegisterString((string)obj, pr.PRobjectId, si, parentId, memberInfo);
  1090.                 else
  1091.                     m_objectManager.RegisterObject(obj, pr.PRobjectId, si, parentId, memberInfo, indexMap);
  1092.             }
  1093.         }
  1094.        
  1095.        
  1096.         // Assigns an internal ID associated with the binary id number
  1097.        
  1098.         // Older formatters generate ids for valuetypes using a different counter than ref types. Newer ones use
  1099.         // a single counter, only value types have a negative value. Need a way to handle older formats.
  1100.         private const int THRESHOLD_FOR_VALUETYPE_IDS = Int32.MaxValue;
  1101.         private bool bOldFormatDetected = false;
  1102.         private IntSizedArray valTypeObjectIdTable;
  1103.        
  1104.         internal long GetId(long objectId)
  1105.         {
  1106.            
  1107.             if (!bFullDeserialization)
  1108.                 InitFullDeserialization();
  1109.            
  1110.            
  1111.             if (objectId > 0)
  1112.                 return objectId;
  1113.            
  1114.             if (bOldFormatDetected || objectId == -1) {
  1115.                 // Alarm bells. This is an old format. Deal with it.
  1116.                 bOldFormatDetected = true;
  1117.                 if (valTypeObjectIdTable == null)
  1118.                     valTypeObjectIdTable = new IntSizedArray();
  1119.                
  1120.                 long tempObjId = 0;
  1121.                 if ((tempObjId = valTypeObjectIdTable[(int)objectId]) == 0) {
  1122.                     tempObjId = THRESHOLD_FOR_VALUETYPE_IDS + objectId;
  1123.                     valTypeObjectIdTable[(int)objectId] = (int)tempObjId;
  1124.                 }
  1125.                 return tempObjId;
  1126.             }
  1127.             return -1 * objectId;
  1128.         }
  1129.        
  1130.        
  1131.         // Trace which includes a single dimensional int array
  1132.         [Conditional("SER_LOGGING")]
  1133.         private void IndexTraceMessage(string message, int[] index)
  1134.         {
  1135.             StringBuilder sb = new StringBuilder(10);
  1136.             sb.Append("[");
  1137.             for (int i = 0; i < index.Length; i++) {
  1138.                 sb.Append(index[i]);
  1139.                 if (i != index.Length - 1)
  1140.                     sb.Append(",");
  1141.             }
  1142.             sb.Append("]");
  1143.             SerTrace.Log(this, message, " ", sb.ToString());
  1144.         }
  1145.        
  1146.         internal Type Bind(string assemblyString, string typeString)
  1147.         {
  1148.             Type type = null;
  1149.             if (m_binder != null && !IsInternalType(assemblyString, typeString))
  1150.                 type = m_binder.BindToType(assemblyString, typeString);
  1151.             if (type == null)
  1152.                 type = FastBindToType(assemblyString, typeString);
  1153.            
  1154.             return type;
  1155.         }
  1156.         private bool IsInternalType(string assemblyString, string typeString)
  1157.         {
  1158.             return (assemblyString == Converter.urtAssemblyString) && ((typeString == "System.DelegateSerializationHolder") || (typeString == "System.UnitySerializationHolder") || (typeString == "System.MemberInfoSerializationHolder"));
  1159.         }
  1160.        
  1161.         internal class TypeNAssembly
  1162.         {
  1163.             public Type type;
  1164.             public string assemblyName;
  1165.         }
  1166.        
  1167.         NameCache typeCache = new NameCache();
  1168.         internal Type FastBindToType(string assemblyName, string typeName)
  1169.         {
  1170.             Type type = null;
  1171.            
  1172.             TypeNAssembly entry = (TypeNAssembly)typeCache.GetCachedValue(typeName);
  1173.            
  1174.             if (entry == null || entry.assemblyName != assemblyName) {
  1175.                 Assembly assm = null;
  1176.                 if (bSimpleAssembly) {
  1177.                     try {
  1178.                         sfileIOPermission.Assert();
  1179.                         try {
  1180.                             StackCrawlMark stackMark = StackCrawlMark.LookForMe;
  1181.                             assm = Assembly.LoadWithPartialNameInternal(assemblyName, null, ref stackMark);
  1182.                             if (assm == null && assemblyName != null)
  1183.                                 assm = Assembly.LoadWithPartialNameInternal(new AssemblyName(assemblyName).Name, null, ref stackMark);
  1184.                         }
  1185.                         finally {
  1186.                             CodeAccessPermission.RevertAssert();
  1187.                         }
  1188.                     }
  1189.                     catch (Exception e) {
  1190.                         SerTrace.Log(this, "FastBindTypeType ", e.ToString());
  1191.                     }
  1192.                 }
  1193.                 else {
  1194.                     try {
  1195.                         sfileIOPermission.Assert();
  1196.                         try {
  1197.                             assm = Assembly.Load(assemblyName);
  1198.                         }
  1199.                         finally {
  1200.                             CodeAccessPermission.RevertAssert();
  1201.                         }
  1202.                     }
  1203.                     catch (Exception e) {
  1204.                         SerTrace.Log(this, "FastBindTypeType ", e.ToString());
  1205.                     }
  1206.                 }
  1207.                 if (assm == null)
  1208.                     return null;
  1209.                
  1210.                 type = FormatterServices.GetTypeFromAssembly(assm, typeName);
  1211.                
  1212.                 if (type == null)
  1213.                     return null;
  1214.                
  1215.                 entry = new TypeNAssembly();
  1216.                 entry.type = type;
  1217.                 entry.assemblyName = assemblyName;
  1218.                 typeCache.SetCachedValue(entry);
  1219.             }
  1220.             return entry.type;
  1221.         }
  1222.        
  1223.        
  1224.         private string previousAssemblyString;
  1225.         private string previousName;
  1226.         private Type previousType;
  1227.         //private int hit;
  1228.        
  1229.         internal Type GetType(BinaryAssemblyInfo assemblyInfo, string name)
  1230.         {
  1231.             Type objectType = null;
  1232.            
  1233.             if (((previousName != null) && (previousName.Length == name.Length) && (previousName.Equals(name))) && ((previousAssemblyString != null) && (previousAssemblyString.Length == assemblyInfo.assemblyString.Length) && (previousAssemblyString.Equals(assemblyInfo.assemblyString)))) {
  1234.                 objectType = previousType;
  1235.                 //Console.WriteLine("Hit "+(++hit)+" "+objectType);
  1236.             }
  1237.             else {
  1238.                 objectType = Bind(assemblyInfo.assemblyString, name);
  1239.                 if (objectType == null)
  1240.                     objectType = FormatterServices.GetTypeFromAssembly(assemblyInfo.GetAssembly(), name);
  1241.                
  1242.                 previousAssemblyString = assemblyInfo.assemblyString;
  1243.                 previousName = name;
  1244.                 previousType = objectType;
  1245.             }
  1246.             //Console.WriteLine("name "+name+" assembly "+assemblyInfo.assemblyString+" objectType "+objectType);
  1247.             return objectType;
  1248.         }
  1249.     }
  1250. }

Developer Fusion