-// ObjectReader.cs
-//
-// Author:
-// Lluis Sanchez Gual (lsg@ctv.es)
-//
-// (C) 2003 Lluis Sanchez Gual
+// ObjectReader.cs\r
+//\r
+// Author:\r
+// Lluis Sanchez Gual (lluis@ideary.com)\r
+// Patrik Torstensson\r
+//\r
+// (C) 2003 Lluis Sanchez Gual\r
\r
// FIXME: Implement the missing binary elements\r
\r
using System.IO;\r
using System.Collections;\r
using System.Reflection;\r
+using System.Runtime.Remoting.Messaging;\r
\r
namespace System.Runtime.Serialization.Formatters.Binary\r
{\r
- public class ObjectReader\r
+ internal class ObjectReader\r
{\r
ISurrogateSelector _surrogateSelector;\r
StreamingContext _context;\r
+ SerializationBinder _binder;\r
\r
ObjectManager _manager;\r
Hashtable _registeredAssemblies = new Hashtable();\r
Hashtable _typeMetadataCache = new Hashtable();\r
\r
- static Type[] _typeCodes;\r
+ object _lastObject = null;\r
+ long _lastObjectID = 0;\r
+ long _rootObjectID = 0;\r
\r
class TypeMetadata\r
{\r
public int NullCount;\r
}\r
\r
- static ObjectReader()\r
- {\r
- _typeCodes = new Type [30];\r
- _typeCodes[(int) TypeCode.Boolean] = typeof (Boolean);\r
- _typeCodes[(int)TypeCode.Byte] = typeof (Byte);\r
- _typeCodes[(int)TypeCode.Char] = typeof (Char);\r
- _typeCodes[(int)TypeCode.DateTime] = typeof (DateTime);\r
- _typeCodes[(int)TypeCode.Decimal] = typeof (Decimal);\r
- _typeCodes[(int)TypeCode.Double] = typeof (Double);\r
- _typeCodes[(int)TypeCode.Int16] = typeof (Int16);\r
- _typeCodes[(int)TypeCode.Int32] = typeof (Int32);\r
- _typeCodes[(int)TypeCode.Int64] = typeof (Int64);\r
- _typeCodes[(int)TypeCode.SByte] = typeof (SByte);\r
- _typeCodes[(int)TypeCode.Single] = typeof (Single);\r
- _typeCodes[(int)TypeCode.UInt16] = typeof (UInt16);\r
- _typeCodes[(int)TypeCode.UInt32] = typeof (UInt32);\r
- _typeCodes[(int)TypeCode.UInt64] = typeof (UInt64);\r
- }\r
-\r
- public ObjectReader(ISurrogateSelector surrogateSelector, StreamingContext context)\r
+ public ObjectReader(ISurrogateSelector surrogateSelector, StreamingContext context, SerializationBinder binder)\r
{\r
_manager = new ObjectManager (surrogateSelector, context);\r
_surrogateSelector = surrogateSelector;\r
_context = context;\r
+ _binder = binder;\r
}\r
\r
- public object ReadObjectGraph (BinaryReader reader)\r
+ public void ReadObjectGraph (BinaryReader reader, bool readHeaders, out object result, out Header[] headers)\r
{\r
- object rootObject = null;\r
- object tmpObject;\r
- SerializationInfo info;\r
- long objectId;\r
-\r
- // Reads the header\r
-\r
- int headerLen = BinaryCommon.BinaryHeader.Length;\r
- reader.ReadBytes (headerLen);\r
+ headers = null;\r
\r
// Reads the objects. The first object in the stream is the\r
// root object.\r
\r
+ while (ReadNextObject (reader))\r
+ {\r
+ if (readHeaders && (headers == null))\r
+ headers = (Header[])CurrentObject;\r
+ else\r
+ if (_rootObjectID == 0) _rootObjectID = _lastObjectID;\r
+ }\r
+\r
+ result = _manager.GetObject (_rootObjectID);\r
+ }\r
+\r
+ public bool ReadNextObject (BinaryReader reader)\r
+ {\r
BinaryElement element = (BinaryElement)reader.ReadByte ();\r
- while (element != BinaryElement.End)\r
+ if (element == BinaryElement.End)\r
{\r
- ReadObject (element, reader, out objectId, out tmpObject, out info);\r
- if (objectId != 0) RegisterObject (objectId, tmpObject, info, 0, null, null);\r
- if (rootObject == null && tmpObject != null) rootObject = tmpObject;\r
- element = (BinaryElement)reader.ReadByte ();\r
+ _manager.DoFixups();\r
+ _manager.RaiseDeserializationEvent();\r
+ return false;\r
}\r
\r
- _manager.DoFixups();\r
+ SerializationInfo info;\r
+ long objectId;\r
+\r
+ ReadObject (element, reader, out objectId, out _lastObject, out info);\r
\r
- return rootObject;\r
+ if (objectId != 0) {\r
+ RegisterObject (objectId, _lastObject, info, 0, null, null);\r
+ _lastObjectID = objectId; \r
+ }\r
+ \r
+ return true;\r
+ }\r
+\r
+ public object CurrentObject\r
+ {\r
+ get { return _lastObject; }\r
}\r
\r
// Reads an object from the stream. The object is registered in the ObjectManager.\r
{\r
long id = (long) reader.ReadUInt32 ();\r
string assemblyName = reader.ReadString ();\r
- Assembly assembly = Assembly.Load (assemblyName);\r
- _registeredAssemblies [id] = assembly;\r
+ _registeredAssemblies [id] = assemblyName;\r
}\r
\r
private void ReadObjectInstance (BinaryReader reader, bool isRuntimeObject, out long objectId, out object value, out SerializationInfo info)\r
\r
private void RegisterObject (long objectId, object objectInstance, SerializationInfo info, long parentObjectId, MemberInfo parentObjectMemeber, int[] indices)\r
{\r
+ if (parentObjectId == 0) indices = null;\r
+\r
if (!objectInstance.GetType().IsValueType || parentObjectId == 0)\r
- _manager.RegisterObject (objectInstance, objectId, info, 0, null, indices);\r
+ _manager.RegisterObject (objectInstance, objectId, info, 0, null, null);\r
else\r
+ {\r
+ if (indices != null) indices = (int[])indices.Clone();\r
_manager.RegisterObject (objectInstance, objectId, info, parentObjectId, parentObjectMemeber, indices);\r
+ }\r
}\r
\r
private void ReadStringIntance (BinaryReader reader, out long objectId, out object value)\r
ArrayStructure structure = (ArrayStructure) reader.ReadByte();\r
\r
int rank = reader.ReadInt32();\r
+\r
+ bool emptyDim = false;\r
int[] lengths = new int[rank];\r
for (int n=0; n<rank; n++)\r
+ {\r
lengths[n] = reader.ReadInt32();\r
+ if (lengths[n] == 0) emptyDim = true;\r
+ }\r
\r
TypeTag code = (TypeTag) reader.ReadByte ();\r
Type elementType = ReadType (reader, code);\r
\r
Array array = Array.CreateInstance (elementType, lengths);\r
\r
+ if (emptyDim) \r
+ { \r
+ val = array;\r
+ return;\r
+ }\r
+\r
int[] indices = new int[rank];\r
\r
// Initialize indexes\r
if (!isRuntimeObject) \r
{\r
long assemblyId = (long)reader.ReadUInt32();\r
- Assembly asm = (Assembly)_registeredAssemblies[assemblyId];\r
- metadata.Type = asm.GetType (className, true);\r
+ metadata.Type = GetDeserializationType (assemblyId, className);\r
}\r
else\r
metadata.Type = Type.GetType (className, true);\r
return members[0];\r
}\r
\r
- private Type ReadType (BinaryReader reader, TypeTag code)\r
+ private Type GetDeserializationType (long assemblyId, string className)\r
+ {\r
+ string assemblyName = (string)_registeredAssemblies[assemblyId];\r
+\r
+ if (_binder == null)\r
+ {\r
+ Assembly assembly = Assembly.Load (assemblyName);\r
+ return assembly.GetType (className, true);\r
+ }\r
+ else\r
+ return _binder.BindToType (assemblyName, className);\r
+ }\r
+\r
+ public Type ReadType (BinaryReader reader, TypeTag code)\r
{\r
switch (code)\r
{\r
case TypeTag.PrimitiveType:\r
- return _typeCodes [reader.ReadByte() + 1];\r
+ return BinaryCommon.GetTypeFromCode (reader.ReadByte());\r
\r
case TypeTag.String:\r
return typeof(string);\r
{\r
string name = reader.ReadString ();\r
long asmid = (long) reader.ReadUInt32();\r
- Assembly asm = (Assembly)_registeredAssemblies[asmid];\r
- return asm.GetType (name, true);\r
+ return GetDeserializationType (asmid, name);\r
}\r
\r
case TypeTag.ArrayOfObject:\r
return typeof(string[]);\r
\r
case TypeTag.ArrayOfPrimitiveType:\r
- Type elementType = _typeCodes [reader.ReadByte()+1];\r
+ Type elementType = BinaryCommon.GetTypeFromCode (reader.ReadByte());\r
return Type.GetType(elementType.FullName + "[]");\r
\r
default:\r
}\r
}\r
\r
- private object ReadPrimitiveTypeValue (BinaryReader reader, Type type)\r
+ public static object ReadPrimitiveTypeValue (BinaryReader reader, Type type)\r
{\r
+ if (type == null) return null;\r
+\r
switch (Type.GetTypeCode (type))\r
{\r
case TypeCode.Boolean:\r
case TypeCode.UInt64:\r
return reader.ReadUInt64();\r
\r
+ case TypeCode.String:\r
+ return reader.ReadString();\r
+\r
default:\r
throw new NotSupportedException ("Unsupported primitive type: " + type.FullName);\r
}\r