-// ObjectReader.cs
+// ObjectReader.cs\r
+//\r
+// Author:\r
+// Lluis Sanchez Gual (lluis@ideary.com)\r
+// Patrik Torstensson\r
+//\r
+// (C) 2003 Lluis Sanchez Gual\r
+
//
-// Author:
-// Lluis Sanchez Gual (lluis@ideary.com)
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// (C) 2003 Lluis Sanchez Gual
-\r
-// FIXME: Implement the missing binary elements\r
\r
using System;\r
using System.Runtime.Serialization;\r
using System.Collections;\r
using System.Reflection;\r
using System.Runtime.Remoting.Messaging;\r
+using System.Globalization;\r
\r
namespace System.Runtime.Serialization.Formatters.Binary\r
{\r
internal class ObjectReader\r
{\r
+ BinaryFormatter _formatter;\r
ISurrogateSelector _surrogateSelector;\r
StreamingContext _context;\r
+ SerializationBinder _binder;\r
+ \r
+#if NET_1_1\r
+ TypeFilterLevel _filterLevel;\r
+#endif\r
\r
ObjectManager _manager;\r
Hashtable _registeredAssemblies = new Hashtable();\r
Hashtable _typeMetadataCache = new Hashtable();\r
\r
object _lastObject = null;\r
+ long _lastObjectID = 0;\r
+ long _rootObjectID = 0;
+ byte[] arrayBuffer;
+ int ArrayBufferLength = 4096;\r
\r
class TypeMetadata\r
{\r
public Type Type;\r
public Type[] MemberTypes;\r
public string[] MemberNames;\r
+ public MemberInfo[] MemberInfos;\r
public int FieldCount;\r
public bool NeedsSerializationInfo;\r
}\r
public int NullCount;\r
}\r
\r
- public ObjectReader(ISurrogateSelector surrogateSelector, StreamingContext context)\r
+ public ObjectReader (BinaryFormatter formatter)\r
{\r
- _manager = new ObjectManager (surrogateSelector, context);\r
- _surrogateSelector = surrogateSelector;\r
- _context = context;\r
+ _formatter = formatter;\r
+ _surrogateSelector = formatter.SurrogateSelector;\r
+ _context = formatter.Context;\r
+ _binder = formatter.Binder;\r
+ _manager = new ObjectManager (_surrogateSelector, _context);\r
+ \r
+#if NET_1_1\r
+ _filterLevel = formatter.FilterLevel;\r
+#endif\r
}\r
\r
- public object ReadObjectGraph (BinaryReader reader, bool readHeaders, HeaderHandler headerHandler)\r
+ public void ReadObjectGraph (BinaryReader reader, bool readHeaders, out object result, out Header[] headers)\r
{\r
- object rootObject = null;\r
- Header[] headers = null;\r
+ headers = null;\r
\r
// Reads the objects. The first object in the stream is the\r
// root object.\r
if (readHeaders && (headers == null))\r
headers = (Header[])CurrentObject;\r
else\r
- if (rootObject == null) rootObject = CurrentObject;\r
+ if (_rootObjectID == 0) _rootObjectID = _lastObjectID;\r
}\r
\r
- if (readHeaders && headerHandler != null)\r
- headerHandler (headers);\r
-\r
- return rootObject;\r
+ result = _manager.GetObject (_rootObjectID);\r
}\r
\r
public bool ReadNextObject (BinaryReader reader)\r
if (element == BinaryElement.End)\r
{\r
_manager.DoFixups();\r
+\r
+ _manager.RaiseDeserializationEvent();\r
return false;\r
}\r
\r
\r
ReadObject (element, reader, out objectId, out _lastObject, out info);\r
\r
- if (objectId != 0) \r
+ if (objectId != 0) {\r
RegisterObject (objectId, _lastObject, info, 0, null, null);\r
-\r
+ _lastObjectID = objectId; \r
+ }\r
+ \r
return true;\r
}\r
\r
ReadRefTypeObjectInstance (reader, out objectId, out value, out info);\r
break;\r
\r
+ case BinaryElement.UntypedRuntimeObject:\r
+ ReadObjectInstance (reader, true, false, out objectId, out value, out info);\r
+ break;\r
+\r
+ case BinaryElement.UntypedExternalObject:\r
+ ReadObjectInstance (reader, false, false, out objectId, out value, out info);\r
+ break;\r
+\r
case BinaryElement.RuntimeObject:\r
- ReadObjectInstance (reader, true, out objectId, out value, out info);\r
+ ReadObjectInstance (reader, true, true, out objectId, out value, out info);\r
break;\r
\r
case BinaryElement.ExternalObject:\r
- ReadObjectInstance (reader, false, out objectId, out value, out info);\r
+ ReadObjectInstance (reader, false, true, out objectId, out value, out info);\r
break;\r
\r
case BinaryElement.String:\r
ReadGenericArray (reader, out objectId, out value);\r
break;\r
\r
+\r
case BinaryElement.BoxedPrimitiveTypeValue:\r
value = ReadBoxedPrimitiveTypeValue (reader);\r
objectId = 0;\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
+ private void ReadObjectInstance (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo, out long objectId, out object value, out SerializationInfo info)\r
{\r
objectId = (long) reader.ReadUInt32 ();\r
\r
- TypeMetadata metadata = ReadTypeMetadata (reader, isRuntimeObject);\r
+ TypeMetadata metadata = ReadTypeMetadata (reader, isRuntimeObject, hasTypeInfo);\r
ReadObjectContent (reader, metadata, objectId, out value, out info);\r
}\r
\r
\r
private void ReadObjectContent (BinaryReader reader, TypeMetadata metadata, long objectId, out object objectInstance, out SerializationInfo info)\r
{\r
- objectInstance = FormatterServices.GetUninitializedObject (metadata.Type);\r
+#if NET_1_1\r
+ if (_filterLevel == TypeFilterLevel.Low)\r
+ objectInstance = FormatterServices.GetSafeUninitializedObject (metadata.Type);\r
+ else\r
+#endif\r
+ objectInstance = FormatterServices.GetUninitializedObject (metadata.Type);\r
+ \r
info = metadata.NeedsSerializationInfo ? new SerializationInfo(metadata.Type, new FormatterConverter()) : null;\r
\r
- for (int n=0; n<metadata.FieldCount; n++)\r
- ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberNames[n], null);\r
+ if (metadata.MemberNames != null)\r
+ for (int n=0; n<metadata.FieldCount; n++)\r
+ ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberNames[n], null, null);\r
+ else\r
+ for (int n=0; n<metadata.FieldCount; n++)\r
+ ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberInfos[n].Name, metadata.MemberInfos[n], null);\r
}\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
private void ReadGenericArray (BinaryReader reader, out long objectId, out object val)\r
{\r
objectId = (long) reader.ReadUInt32 ();\r
- ArrayStructure structure = (ArrayStructure) reader.ReadByte();\r
+ // Array structure
+ reader.ReadByte();\r
\r
int rank = reader.ReadInt32();\r
\r
bool end = false;\r
while (!end)\r
{\r
- ReadValue (reader, array, objectId, null, elementType, null, indices);\r
+ ReadValue (reader, array, objectId, null, elementType, null, null, indices);\r
\r
for (int dim = array.Rank-1; dim >= 0; dim--)\r
{\r
int length = reader.ReadInt32 ();\r
Type elementType = ReadType (reader, TypeTag.PrimitiveType);\r
\r
- Array array = Array.CreateInstance (elementType, length);\r
- for (int n = 0; n < length; n++)\r
- array.SetValue (ReadPrimitiveTypeValue (reader, elementType), n);\r
+ switch (Type.GetTypeCode (elementType))\r
+ {\r
+ case TypeCode.Boolean: {\r
+ bool[] arr = new bool [length];\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadBoolean();\r
+ val = arr;\r
+ break;\r
+ }\r
\r
- val = array;\r
+ case TypeCode.Byte: {\r
+ byte[] arr = new byte [length];\r
+ int pos = 0;\r
+ while (pos < length) {\r
+ int nr = reader.Read (arr, pos, length - pos);\r
+ if (nr == 0) break;\r
+ pos += nr;\r
+ }\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Char: {\r
+ char[] arr = new char [length];\r
+ int pos = 0;\r
+ while (pos < length) {\r
+ int nr = reader.Read (arr, pos, length - pos);\r
+ if (nr == 0) break;\r
+ pos += nr;\r
+ }\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.DateTime: {\r
+ DateTime[] arr = new DateTime [length];\r
+ for (int n = 0; n < length; n++) arr [n] = new DateTime (reader.ReadInt64());\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Decimal: {\r
+ Decimal[] arr = new Decimal [length];\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadDecimal();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Double: {\r
+ Double[] arr = new Double [length];
+ if (length > 2)\r
+ BlockRead (reader, arr, 8);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadDouble();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Int16: {\r
+ short[] arr = new short [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 2);
+ else
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadInt16();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Int32: {\r
+ int[] arr = new int [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 4);
+ else
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadInt32();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Int64: {\r
+ long[] arr = new long [length];
+ if (length > 2)\r
+ BlockRead (reader, arr, 8);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadInt64();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.SByte: {\r
+ sbyte[] arr = new sbyte [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 1);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadSByte();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.Single: {\r
+ float[] arr = new float [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 4);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadSingle();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.UInt16: {\r
+ ushort[] arr = new ushort [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 2);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt16();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.UInt32: {\r
+ uint[] arr = new uint [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 4);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt32();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.UInt64: {\r
+ ulong[] arr = new ulong [length];\r
+ if (length > 2)\r
+ BlockRead (reader, arr, 8);
+ else\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt64();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ case TypeCode.String: {\r
+ string[] arr = new string [length];\r
+ for (int n = 0; n < length; n++) arr [n] = reader.ReadString();\r
+ val = arr;\r
+ break;\r
+ }\r
+\r
+ default: {\r
+ if (elementType == typeof(TimeSpan)) {\r
+ TimeSpan[] arr = new TimeSpan [length];\r
+ for (int n = 0; n < length; n++) arr [n] = new TimeSpan (reader.ReadInt64 ());\r
+ val = arr;\r
+ }\r
+ else\r
+ throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);\r
+ break;\r
+ }\r
+ } \r
}\r
\r
+ private void BlockRead (BinaryReader reader, Array array, int dataSize)\r
+ {
+ int totalSize = Buffer.ByteLength (array);
+
+ if (arrayBuffer == null || (totalSize > arrayBuffer.Length && arrayBuffer.Length != ArrayBufferLength))
+ arrayBuffer = new byte [totalSize <= ArrayBufferLength ? totalSize : ArrayBufferLength];
+
+ int pos = 0;
+ while (totalSize > 0) {
+ int size = totalSize < arrayBuffer.Length ? totalSize : arrayBuffer.Length;
+ int ap = 0;
+ do {
+ int nr = reader.Read (arrayBuffer, ap, size - ap);\r
+ if (nr == 0) break;\r
+ ap += nr;
+ } while (ap < size);
+
+ if (!BitConverter.IsLittleEndian && dataSize > 1)
+ BinaryCommon.SwapBytes (arrayBuffer, size, dataSize);
+
+ Buffer.BlockCopy (arrayBuffer, 0, array, pos, size);
+ totalSize -= size;
+ pos += size;
+ }
+ }
+
+\r
private void ReadArrayOfObject (BinaryReader reader, out long objectId, out object array)\r
{\r
ReadSimpleArray (reader, typeof (object), out objectId, out array);\r
for (int n = 0; n < length; n++)\r
{\r
indices[0] = n;\r
- ReadValue (reader, array, objectId, null, elementType, null, indices);\r
+ ReadValue (reader, array, objectId, null, elementType, null, null, indices);\r
n = indices[0];\r
}\r
val = array;\r
}\r
\r
- private TypeMetadata ReadTypeMetadata (BinaryReader reader, bool isRuntimeObject)\r
+ private TypeMetadata ReadTypeMetadata (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo)\r
{\r
TypeMetadata metadata = new TypeMetadata();\r
\r
Type[] types = new Type[fieldCount];\r
string[] names = new string[fieldCount];\r
\r
- TypeTag[] codes = new TypeTag[fieldCount];\r
-\r
for (int n=0; n<fieldCount; n++)\r
names [n] = reader.ReadString ();\r
\r
- for (int n=0; n<fieldCount; n++)\r
- codes [n] = (TypeTag) reader.ReadByte ();\r
-\r
- for (int n=0; n<fieldCount; n++)\r
- types [n] = ReadType (reader, codes[n]);\r
+ if (hasTypeInfo)\r
+ {\r
+ TypeTag[] codes = new TypeTag[fieldCount];\r
\r
+ for (int n=0; n<fieldCount; n++)\r
+ codes [n] = (TypeTag) reader.ReadByte ();\r
+ \r
+ for (int n=0; n<fieldCount; n++)\r
+ types [n] = ReadType (reader, codes[n]);\r
+ }\r
+ \r
// Gets the type\r
\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
throw new SerializationException("Serializable objects must be marked with the Serializable attribute");\r
\r
metadata.NeedsSerializationInfo = (metadata.Type.GetInterface ("ISerializable") != null);\r
+ if (!metadata.NeedsSerializationInfo)\r
+ {\r
+ metadata.MemberInfos = new MemberInfo [fieldCount];\r
+ for (int n=0; n<fieldCount; n++)\r
+ {\r
+ FieldInfo field = null;\r
+ string memberName = names[n];\r
+ \r
+ int i = memberName.IndexOf ('+');\r
+ if (i != -1) {\r
+ string baseTypeName = names[n].Substring (0,i);\r
+ memberName = names[n].Substring (i+1);\r
+ Type t = metadata.Type.BaseType;\r
+ while (t != null) {\r
+ if (t.Name == baseTypeName) {\r
+ field = t.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\r
+ break;\r
+ }\r
+ else\r
+ t = t.BaseType;\r
+ }\r
+ }\r
+ else\r
+ field = metadata.Type.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\r
+ \r
+ if (field == null) throw new SerializationException ("Field \"" + names[n] + "\" not found in class " + metadata.Type.FullName);\r
+ metadata.MemberInfos [n] = field;\r
+ \r
+ if (!hasTypeInfo) {\r
+ types [n] = field.FieldType;\r
+ }\r
+ }\r
+ metadata.MemberNames = null; // Info now in MemberInfos\r
+ }\r
}\r
\r
// Registers the type's metadata so it can be reused later if\r
}\r
\r
\r
- private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, int[] indices)\r
+ private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices)\r
{\r
// Reads a value from the stream and assigns it to the member of an object\r
\r
if (BinaryCommon.IsPrimitive (valueType))\r
{\r
val = ReadPrimitiveTypeValue (reader, valueType);\r
- SetObjectValue (parentObject, fieldName, info, val, valueType, indices);\r
+ SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);\r
return;\r
}\r
\r
{\r
// Just read the id of the referred object and record a fixup\r
long childObjectId = (long) reader.ReadUInt32();\r
- RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, indices);\r
+ RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices);\r
return;\r
}\r
\r
{\r
if (val.GetType().IsValueType)\r
{\r
- RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, indices);\r
+ RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, memberInfo, indices);\r
hasFixup = true;\r
}\r
\r
// Register the value\r
\r
- if (info == null && !parentObject.GetType().IsArray)\r
- RegisterObject (objectId, val, objectInfo, parentObjectId, GetObjectMember(parentObject, fieldName), null);\r
+ if (info == null && !(parentObject is Array))\r
+ RegisterObject (objectId, val, objectInfo, parentObjectId, memberInfo, null);\r
else\r
RegisterObject (objectId, val, objectInfo, parentObjectId, null, indices);\r
}\r
// Assign the value to the parent object, unless there is a fixup\r
\r
if (!hasFixup) \r
- SetObjectValue (parentObject, fieldName, info, val, valueType, indices);\r
+ SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);\r
}\r
\r
- private void SetObjectValue (object parentObject, string fieldName, SerializationInfo info, object value, Type valueType, int[] indices)\r
+ private void SetObjectValue (object parentObject, string fieldName, MemberInfo memberInfo, SerializationInfo info, object value, Type valueType, int[] indices)\r
{\r
if (value is IObjectReference)\r
value = ((IObjectReference)value).GetRealObject (_context);\r
\r
- if (parentObject.GetType().IsArray) \r
+ if (parentObject is Array) \r
{\r
if (value is ArrayNullFiller) \r
{\r
info.AddValue (fieldName, value, valueType);\r
}\r
else {\r
- MemberInfo member = GetObjectMember(parentObject, fieldName);\r
- if (member is FieldInfo)\r
- ((FieldInfo)member).SetValue (parentObject, value);\r
+ if (memberInfo is FieldInfo)\r
+ ((FieldInfo)memberInfo).SetValue (parentObject, value);\r
else\r
- ((PropertyInfo)member).SetValue (parentObject, value, null);\r
+ ((PropertyInfo)memberInfo).SetValue (parentObject, value, null);\r
}\r
}\r
\r
- private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, int[] indices)\r
+ private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, MemberInfo memberInfo, int[] indices)\r
{\r
if (info != null) {\r
_manager.RecordDelayedFixup (parentObjectId, fieldName, childObjectId);\r
}\r
- else if (parentObject.GetType().IsArray) {\r
+ else if (parentObject is Array) {\r
if (indices.Length == 1)\r
_manager.RecordArrayElementFixup (parentObjectId, indices[0], childObjectId);\r
else\r
_manager.RecordArrayElementFixup (parentObjectId, (int[])indices.Clone(), childObjectId);\r
}\r
else {\r
- _manager.RecordFixup (parentObjectId, GetObjectMember(parentObject, fieldName), childObjectId);\r
+ _manager.RecordFixup (parentObjectId, memberInfo, childObjectId);\r
}\r
}\r
\r
- private MemberInfo GetObjectMember (object parentObject, string fieldName)\r
+ private Type GetDeserializationType (long assemblyId, string className)\r
{\r
- MemberInfo[] members = parentObject.GetType().GetMember (fieldName, MemberTypes.Field | MemberTypes.Property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);\r
- if (members.Length > 1) throw new SerializationException ("There are two public members named \"" + fieldName + "\" in the class hirearchy of " + parentObject.GetType().FullName);\r
- if (members.Length == 0) throw new SerializationException ("Field \"" + fieldName + "\" not found in class " + parentObject.GetType().FullName);\r
- return members[0];\r
+ string assemblyName = (string)_registeredAssemblies[assemblyId];\r
+\r
+ if (_binder != null) {\r
+ Type t = _binder.BindToType (assemblyName, className);\r
+ if (t != null) return t;\r
+ }\r
+ \r
+ Assembly assembly = Assembly.Load (assemblyName);\r
+ return assembly.GetType (className, true);\r
}\r
\r
public Type ReadType (BinaryReader reader, TypeTag code)\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 reader.ReadChar();\r
\r
case TypeCode.DateTime: \r
- long ticks = reader.ReadInt64();\r
- return new DateTime (ticks);\r
+ return new DateTime (reader.ReadInt64());\r
\r
case TypeCode.Decimal:\r
- return reader.ReadDecimal();\r
+ return Decimal.Parse (reader.ReadString(), CultureInfo.InvariantCulture);\r
\r
case TypeCode.Double:\r
return reader.ReadDouble();\r
return reader.ReadString();\r
\r
default:\r
- throw new NotSupportedException ("Unsupported primitive type: " + type.FullName);\r
+ if (type == typeof(TimeSpan))\r
+ return new TimeSpan (reader.ReadInt64 ());\r
+ else\r
+ throw new NotSupportedException ("Unsupported primitive type: " + type.FullName);\r
}\r
}\r
}\r
-}\r
+}