4 // Lluis Sanchez Gual (lluis@ideary.com)
7 // (C) 2003 Lluis Sanchez Gual
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System
.Runtime
.Serialization
;
35 using System
.Collections
;
36 using System
.Reflection
;
37 using System
.Runtime
.Remoting
.Messaging
;
38 using System
.Globalization
;
40 namespace System
.Runtime
.Serialization
.Formatters
.Binary
42 internal class ObjectReader
44 // BinaryFormatter _formatter;
45 ISurrogateSelector _surrogateSelector
;
46 StreamingContext _context
;
47 SerializationBinder _binder
;
50 TypeFilterLevel _filterLevel
;
53 ObjectManager _manager
;
54 Hashtable _registeredAssemblies
= new Hashtable();
55 Hashtable _typeMetadataCache
= new Hashtable();
57 object _lastObject
= null;
58 long _lastObjectID
= 0;
59 long _rootObjectID
= 0;
61 int ArrayBufferLength
= 4096;
66 public Type
[] MemberTypes
;
67 public string[] MemberNames
;
68 public MemberInfo
[] MemberInfos
;
69 public int FieldCount
;
70 public bool NeedsSerializationInfo
;
75 public ArrayNullFiller(int count
) { NullCount = count; }
79 public ObjectReader (BinaryFormatter formatter
)
81 // _formatter = formatter;
82 _surrogateSelector
= formatter
.SurrogateSelector
;
83 _context
= formatter
.Context
;
84 _binder
= formatter
.Binder
;
85 _manager
= new ObjectManager (_surrogateSelector
, _context
);
88 _filterLevel
= formatter
.FilterLevel
;
92 public void ReadObjectGraph (BinaryReader reader
, bool readHeaders
, out object result
, out Header
[] headers
)
94 BinaryElement elem
= (BinaryElement
)reader
.ReadByte ();
95 ReadObjectGraph (elem
, reader
, readHeaders
, out result
, out headers
);
98 public void ReadObjectGraph (BinaryElement elem
, BinaryReader reader
, bool readHeaders
, out object result
, out Header
[] headers
)
102 // Reads the objects. The first object in the stream is the
104 bool next
= ReadNextObject (elem
, reader
);
107 if (readHeaders
&& (headers
== null))
108 headers
= (Header
[])CurrentObject
;
110 if (_rootObjectID
== 0) _rootObjectID
= _lastObjectID
;
111 } while (ReadNextObject (reader
));
114 result
= _manager
.GetObject (_rootObjectID
);
117 bool ReadNextObject (BinaryElement element
, BinaryReader reader
)
119 if (element
== BinaryElement
.End
)
123 _manager
.RaiseDeserializationEvent();
127 SerializationInfo info
;
130 ReadObject (element
, reader
, out objectId
, out _lastObject
, out info
);
133 RegisterObject (objectId
, _lastObject
, info
, 0, null, null);
134 _lastObjectID
= objectId
;
140 public bool ReadNextObject (BinaryReader reader
)
142 BinaryElement element
= (BinaryElement
)reader
.ReadByte ();
143 if (element
== BinaryElement
.End
)
147 _manager
.RaiseDeserializationEvent();
151 SerializationInfo info
;
154 ReadObject (element
, reader
, out objectId
, out _lastObject
, out info
);
157 RegisterObject (objectId
, _lastObject
, info
, 0, null, null);
158 _lastObjectID
= objectId
;
164 public object CurrentObject
166 get { return _lastObject; }
169 // Reads an object from the stream. The object is registered in the ObjectManager.
170 // The result can be either the object instance
171 // or the id of the object (when what is found in the stream is an object reference).
172 // If an object instance is read, the objectId is set to 0.
174 private void ReadObject (BinaryElement element
, BinaryReader reader
, out long objectId
, out object value, out SerializationInfo info
)
178 case BinaryElement
.RefTypeObject
:
179 ReadRefTypeObjectInstance (reader
, out objectId
, out value, out info
);
182 case BinaryElement
.UntypedRuntimeObject
:
183 ReadObjectInstance (reader
, true, false, out objectId
, out value, out info
);
186 case BinaryElement
.UntypedExternalObject
:
187 ReadObjectInstance (reader
, false, false, out objectId
, out value, out info
);
190 case BinaryElement
.RuntimeObject
:
191 ReadObjectInstance (reader
, true, true, out objectId
, out value, out info
);
194 case BinaryElement
.ExternalObject
:
195 ReadObjectInstance (reader
, false, true, out objectId
, out value, out info
);
198 case BinaryElement
.String
:
200 ReadStringIntance (reader
, out objectId
, out value);
203 case BinaryElement
.GenericArray
:
205 ReadGenericArray (reader
, out objectId
, out value);
209 case BinaryElement
.BoxedPrimitiveTypeValue
:
210 value = ReadBoxedPrimitiveTypeValue (reader
);
215 case BinaryElement
.NullValue
:
221 case BinaryElement
.Assembly
:
222 ReadAssembly (reader
);
223 ReadObject ((BinaryElement
)reader
.ReadByte (), reader
, out objectId
, out value, out info
);
226 case BinaryElement
.ArrayFiller8b
:
227 value = new ArrayNullFiller(reader
.ReadByte());
232 case BinaryElement
.ArrayFiller32b
:
233 value = new ArrayNullFiller(reader
.ReadInt32());
238 case BinaryElement
.ArrayOfPrimitiveType
:
239 ReadArrayOfPrimitiveType (reader
, out objectId
, out value);
243 case BinaryElement
.ArrayOfObject
:
244 ReadArrayOfObject (reader
, out objectId
, out value);
248 case BinaryElement
.ArrayOfString
:
249 ReadArrayOfString (reader
, out objectId
, out value);
254 throw new SerializationException ("Unexpected binary element: " + (int)element
);
258 private void ReadAssembly (BinaryReader reader
)
260 long id
= (long) reader
.ReadUInt32 ();
261 string assemblyName
= reader
.ReadString ();
262 _registeredAssemblies
[id
] = assemblyName
;
265 private void ReadObjectInstance (BinaryReader reader
, bool isRuntimeObject
, bool hasTypeInfo
, out long objectId
, out object value, out SerializationInfo info
)
267 objectId
= (long) reader
.ReadUInt32 ();
269 TypeMetadata metadata
= ReadTypeMetadata (reader
, isRuntimeObject
, hasTypeInfo
);
270 ReadObjectContent (reader
, metadata
, objectId
, out value, out info
);
273 private void ReadRefTypeObjectInstance (BinaryReader reader
, out long objectId
, out object value, out SerializationInfo info
)
275 objectId
= (long) reader
.ReadUInt32 ();
276 long refTypeObjectId
= (long) reader
.ReadUInt32 ();
278 // Gets the type of the referred object and its metadata
280 object refObj
= _manager
.GetObject (refTypeObjectId
);
281 if (refObj
== null) throw new SerializationException ("Invalid binary format");
282 TypeMetadata metadata
= (TypeMetadata
)_typeMetadataCache
[refObj
.GetType()];
284 ReadObjectContent (reader
, metadata
, objectId
, out value, out info
);
287 private void ReadObjectContent (BinaryReader reader
, TypeMetadata metadata
, long objectId
, out object objectInstance
, out SerializationInfo info
)
289 if (_filterLevel
== TypeFilterLevel
.Low
)
290 objectInstance
= FormatterServices
.GetSafeUninitializedObject (metadata
.Type
);
292 objectInstance
= FormatterServices
.GetUninitializedObject (metadata
.Type
);
293 _manager
.RaiseOnDeserializingEvent (objectInstance
);
295 info
= metadata
.NeedsSerializationInfo
? new SerializationInfo(metadata
.Type
, new FormatterConverter()) : null;
297 if (metadata
.MemberNames
!= null)
298 for (int n
=0; n
<metadata
.FieldCount
; n
++)
299 ReadValue (reader
, objectInstance
, objectId
, info
, metadata
.MemberTypes
[n
], metadata
.MemberNames
[n
], null, null);
301 for (int n
=0; n
<metadata
.FieldCount
; n
++)
302 ReadValue (reader
, objectInstance
, objectId
, info
, metadata
.MemberTypes
[n
], metadata
.MemberInfos
[n
].Name
, metadata
.MemberInfos
[n
], null);
305 private void RegisterObject (long objectId
, object objectInstance
, SerializationInfo info
, long parentObjectId
, MemberInfo parentObjectMemeber
, int[] indices
)
307 if (parentObjectId
== 0) indices
= null;
309 if (!objectInstance
.GetType().IsValueType
|| parentObjectId
== 0)
310 _manager
.RegisterObject (objectInstance
, objectId
, info
, 0, null, null);
313 if (indices
!= null) indices
= (int[])indices
.Clone();
314 _manager
.RegisterObject (objectInstance
, objectId
, info
, parentObjectId
, parentObjectMemeber
, indices
);
318 private void ReadStringIntance (BinaryReader reader
, out long objectId
, out object value)
320 objectId
= (long) reader
.ReadUInt32 ();
321 value = reader
.ReadString ();
324 private void ReadGenericArray (BinaryReader reader
, out long objectId
, out object val
)
326 objectId
= (long) reader
.ReadUInt32 ();
330 int rank
= reader
.ReadInt32();
332 bool emptyDim
= false;
333 int[] lengths
= new int[rank
];
334 for (int n
=0; n
<rank
; n
++)
336 lengths
[n
] = reader
.ReadInt32();
337 if (lengths
[n
] == 0) emptyDim
= true;
340 TypeTag code
= (TypeTag
) reader
.ReadByte ();
341 Type elementType
= ReadType (reader
, code
);
343 Array array
= Array
.CreateInstance (elementType
, lengths
);
351 int[] indices
= new int[rank
];
353 // Initialize indexes
354 for (int dim
= rank
-1; dim
>= 0; dim
--)
355 indices
[dim
] = array
.GetLowerBound (dim
);
360 ReadValue (reader
, array
, objectId
, null, elementType
, null, null, indices
);
362 for (int dim
= array
.Rank
-1; dim
>= 0; dim
--)
365 if (indices
[dim
] > array
.GetUpperBound (dim
))
369 indices
[dim
] = array
.GetLowerBound (dim
);
370 continue; // Increment the next dimension's index
372 end
= true; // That was the last dimension. Finished.
380 private object ReadBoxedPrimitiveTypeValue (BinaryReader reader
)
382 Type type
= ReadType (reader
, TypeTag
.PrimitiveType
);
383 return ReadPrimitiveTypeValue (reader
, type
);
386 private void ReadArrayOfPrimitiveType (BinaryReader reader
, out long objectId
, out object val
)
388 objectId
= (long) reader
.ReadUInt32 ();
389 int length
= reader
.ReadInt32 ();
390 Type elementType
= ReadType (reader
, TypeTag
.PrimitiveType
);
392 switch (Type
.GetTypeCode (elementType
))
394 case TypeCode
.Boolean
: {
395 bool[] arr
= new bool [length
];
396 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadBoolean();
401 case TypeCode
.Byte
: {
402 byte[] arr
= new byte [length
];
404 while (pos
< length
) {
405 int nr
= reader
.Read (arr
, pos
, length
- pos
);
413 case TypeCode
.Char
: {
414 char[] arr
= new char [length
];
416 while (pos
< length
) {
417 int nr
= reader
.Read (arr
, pos
, length
- pos
);
425 case TypeCode
.DateTime
: {
426 DateTime
[] arr
= new DateTime
[length
];
427 for (int n
= 0; n
< length
; n
++) {
428 arr
[n
] = DateTime
.FromBinary (reader
.ReadInt64 ());
434 case TypeCode
.Decimal
: {
435 Decimal
[] arr
= new Decimal
[length
];
436 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadDecimal();
441 case TypeCode
.Double
: {
442 Double
[] arr
= new Double
[length
];
444 BlockRead (reader
, arr
, 8);
446 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadDouble();
451 case TypeCode
.Int16
: {
452 short[] arr
= new short [length
];
454 BlockRead (reader
, arr
, 2);
456 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadInt16();
461 case TypeCode
.Int32
: {
462 int[] arr
= new int [length
];
464 BlockRead (reader
, arr
, 4);
466 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadInt32();
471 case TypeCode
.Int64
: {
472 long[] arr
= new long [length
];
474 BlockRead (reader
, arr
, 8);
476 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadInt64();
481 case TypeCode
.SByte
: {
482 sbyte[] arr
= new sbyte [length
];
484 BlockRead (reader
, arr
, 1);
486 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadSByte();
491 case TypeCode
.Single
: {
492 float[] arr
= new float [length
];
494 BlockRead (reader
, arr
, 4);
496 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadSingle();
501 case TypeCode
.UInt16
: {
502 ushort[] arr
= new ushort [length
];
504 BlockRead (reader
, arr
, 2);
506 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadUInt16();
511 case TypeCode
.UInt32
: {
512 uint[] arr
= new uint [length
];
514 BlockRead (reader
, arr
, 4);
516 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadUInt32();
521 case TypeCode
.UInt64
: {
522 ulong[] arr
= new ulong [length
];
524 BlockRead (reader
, arr
, 8);
526 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadUInt64();
531 case TypeCode
.String
: {
532 string[] arr
= new string [length
];
533 for (int n
= 0; n
< length
; n
++) arr
[n
] = reader
.ReadString();
539 if (elementType
== typeof(TimeSpan
)) {
540 TimeSpan
[] arr
= new TimeSpan
[length
];
541 for (int n
= 0; n
< length
; n
++) arr
[n
] = new TimeSpan (reader
.ReadInt64 ());
545 throw new NotSupportedException ("Unsupported primitive type: " + elementType
.FullName
);
551 private void BlockRead (BinaryReader reader
, Array array
, int dataSize
)
553 int totalSize
= Buffer
.ByteLength (array
);
555 if (arrayBuffer
== null || (totalSize
> arrayBuffer
.Length
&& arrayBuffer
.Length
!= ArrayBufferLength
))
556 arrayBuffer
= new byte [totalSize
<= ArrayBufferLength
? totalSize
: ArrayBufferLength
];
559 while (totalSize
> 0) {
560 int size
= totalSize
< arrayBuffer
.Length
? totalSize
: arrayBuffer
.Length
;
563 int nr
= reader
.Read (arrayBuffer
, ap
, size
- ap
);
568 if (!BitConverter
.IsLittleEndian
&& dataSize
> 1)
569 BinaryCommon
.SwapBytes (arrayBuffer
, size
, dataSize
);
571 Buffer
.BlockCopy (arrayBuffer
, 0, array
, pos
, size
);
578 private void ReadArrayOfObject (BinaryReader reader
, out long objectId
, out object array
)
580 ReadSimpleArray (reader
, typeof (object), out objectId
, out array
);
583 private void ReadArrayOfString (BinaryReader reader
, out long objectId
, out object array
)
585 ReadSimpleArray (reader
, typeof (string), out objectId
, out array
);
588 private void ReadSimpleArray (BinaryReader reader
, Type elementType
, out long objectId
, out object val
)
590 objectId
= (long) reader
.ReadUInt32 ();
591 int length
= reader
.ReadInt32 ();
592 int[] indices
= new int[1];
594 Array array
= Array
.CreateInstance (elementType
, length
);
595 for (int n
= 0; n
< length
; n
++)
598 ReadValue (reader
, array
, objectId
, null, elementType
, null, null, indices
);
604 private TypeMetadata
ReadTypeMetadata (BinaryReader reader
, bool isRuntimeObject
, bool hasTypeInfo
)
606 TypeMetadata metadata
= new TypeMetadata();
608 string className
= reader
.ReadString ();
609 int fieldCount
= reader
.ReadInt32 ();
611 Type
[] types
= new Type
[fieldCount
];
612 string[] names
= new string[fieldCount
];
614 for (int n
=0; n
<fieldCount
; n
++)
615 names
[n
] = reader
.ReadString ();
619 TypeTag
[] codes
= new TypeTag
[fieldCount
];
621 for (int n
=0; n
<fieldCount
; n
++)
622 codes
[n
] = (TypeTag
) reader
.ReadByte ();
624 for (int n
=0; n
<fieldCount
; n
++) {
625 Type t
= ReadType (reader
, codes
[n
], false);
626 // The field's type could not be resolved: assume it is an object.
635 if (!isRuntimeObject
)
637 long assemblyId
= (long)reader
.ReadUInt32();
638 metadata
.Type
= GetDeserializationType (assemblyId
, className
);
641 metadata
.Type
= Type
.GetType (className
, true);
643 metadata
.MemberTypes
= types
;
644 metadata
.MemberNames
= names
;
645 metadata
.FieldCount
= names
.Length
;
647 // Now check if this objects needs a SerializationInfo struct for deserialziation.
648 // SerializationInfo is needed if the object has to be deserialized using
649 // a serialization surrogate, or if it implements ISerializable.
651 if (_surrogateSelector
!= null)
653 // check if the surrogate selector handles objects of the given type.
654 ISurrogateSelector selector
;
655 ISerializationSurrogate surrogate
= _surrogateSelector
.GetSurrogate (metadata
.Type
, _context
, out selector
);
656 metadata
.NeedsSerializationInfo
= (surrogate
!= null);
659 if (!metadata
.NeedsSerializationInfo
)
661 // Check if the object is marked with the Serializable attribute
663 if (!metadata
.Type
.IsSerializable
)
664 throw new SerializationException("Serializable objects must be marked with the Serializable attribute");
666 metadata
.NeedsSerializationInfo
= typeof (ISerializable
).IsAssignableFrom (metadata
.Type
);
667 if (!metadata
.NeedsSerializationInfo
)
669 metadata
.MemberInfos
= new MemberInfo
[fieldCount
];
670 for (int n
=0; n
<fieldCount
; n
++)
672 FieldInfo field
= null;
673 string memberName
= names
[n
];
675 int i
= memberName
.IndexOf ('+');
677 string baseTypeName
= names
[n
].Substring (0,i
);
678 memberName
= names
[n
].Substring (i
+1);
679 Type t
= metadata
.Type
.BaseType
;
681 if (t
.Name
== baseTypeName
) {
682 field
= t
.GetField (memberName
, BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
690 field
= metadata
.Type
.GetField (memberName
, BindingFlags
.Instance
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
692 if (field
== null) throw new SerializationException ("Field \"" + names
[n
] + "\" not found in class " + metadata
.Type
.FullName
);
693 metadata
.MemberInfos
[n
] = field
;
696 types
[n
] = field
.FieldType
;
699 metadata
.MemberNames
= null; // Info now in MemberInfos
703 // Registers the type's metadata so it can be reused later if
704 // a RefTypeObject element is found
706 if (!_typeMetadataCache
.ContainsKey (metadata
.Type
))
707 _typeMetadataCache
[metadata
.Type
] = metadata
;
713 private void ReadValue (BinaryReader reader
, object parentObject
, long parentObjectId
, SerializationInfo info
, Type valueType
, string fieldName
, MemberInfo memberInfo
, int[] indices
)
715 // Reads a value from the stream and assigns it to the member of an object
719 if (BinaryCommon
.IsPrimitive (valueType
))
721 val
= ReadPrimitiveTypeValue (reader
, valueType
);
722 SetObjectValue (parentObject
, fieldName
, memberInfo
, info
, val
, valueType
, indices
);
728 BinaryElement element
= (BinaryElement
)reader
.ReadByte ();
730 if (element
== BinaryElement
.ObjectReference
)
732 // Just read the id of the referred object and record a fixup
733 long childObjectId
= (long) reader
.ReadUInt32();
734 RecordFixup (parentObjectId
, childObjectId
, parentObject
, info
, fieldName
, memberInfo
, indices
);
739 SerializationInfo objectInfo
;
741 ReadObject (element
, reader
, out objectId
, out val
, out objectInfo
);
743 // There are two cases where the object cannot be assigned to the parent
744 // and a fixup must be used:
745 // 1) When what has been read is not an object, but an id of an object that
746 // has not been read yet (an object reference). This is managed in the
747 // previous block of code.
748 // 2) When the read object is a value type object. Value type fields hold
749 // copies of objects, not references. Thus, if the value object that
750 // has been read has pending fixups, those fixups would be made to the
751 // boxed copy in the ObjectManager, and not in the required object instance
753 // First of all register the fixup, and then the object. ObjectManager is more
754 // efficient if done in this order
756 bool hasFixup
= false;
759 if (val
.GetType().IsValueType
)
761 RecordFixup (parentObjectId
, objectId
, parentObject
, info
, fieldName
, memberInfo
, indices
);
765 // Register the value
767 if (info
== null && !(parentObject
is Array
))
768 RegisterObject (objectId
, val
, objectInfo
, parentObjectId
, memberInfo
, null);
770 RegisterObject (objectId
, val
, objectInfo
, parentObjectId
, null, indices
);
772 // Assign the value to the parent object, unless there is a fixup
775 SetObjectValue (parentObject
, fieldName
, memberInfo
, info
, val
, valueType
, indices
);
778 private void SetObjectValue (object parentObject
, string fieldName
, MemberInfo memberInfo
, SerializationInfo info
, object value, Type valueType
, int[] indices
)
780 if (value is IObjectReference
)
781 value = ((IObjectReference
)value).GetRealObject (_context
);
783 if (parentObject
is Array
)
785 if (value is ArrayNullFiller
)
787 // It must be a single dimension array of objects.
788 // Just increase the index. Elements are null by default.
789 int count
= ((ArrayNullFiller
)value).NullCount
;
790 indices
[0] += count
- 1;
793 ((Array
)parentObject
).SetValue (value, indices
);
795 else if (info
!= null) {
796 info
.AddValue (fieldName
, value, valueType
);
799 if (memberInfo
is FieldInfo
)
800 ((FieldInfo
)memberInfo
).SetValue (parentObject
, value);
802 ((PropertyInfo
)memberInfo
).SetValue (parentObject
, value, null);
806 private void RecordFixup (long parentObjectId
, long childObjectId
, object parentObject
, SerializationInfo info
, string fieldName
, MemberInfo memberInfo
, int[] indices
)
809 _manager
.RecordDelayedFixup (parentObjectId
, fieldName
, childObjectId
);
811 else if (parentObject
is Array
) {
812 if (indices
.Length
== 1)
813 _manager
.RecordArrayElementFixup (parentObjectId
, indices
[0], childObjectId
);
815 _manager
.RecordArrayElementFixup (parentObjectId
, (int[])indices
.Clone(), childObjectId
);
818 _manager
.RecordFixup (parentObjectId
, memberInfo
, childObjectId
);
822 private Type
GetDeserializationType (long assemblyId
, string className
)
824 return GetDeserializationType (assemblyId
, className
, true);
827 private Type
GetDeserializationType (long assemblyId
, string className
, bool throwOnError
)
830 string assemblyName
= (string)_registeredAssemblies
[assemblyId
];
832 if (_binder
!= null) {
833 t
= _binder
.BindToType (assemblyName
, className
);
840 assembly
= Assembly
.Load (assemblyName
);
841 } catch (Exception ex
) {
844 throw new SerializationException (String
.Format ("Couldn't find assembly '{0}'", assemblyName
), ex
);
847 t
= assembly
.GetType (className
);
854 throw new SerializationException (String
.Format ("Couldn't find type '{0}' in assembly '{1}'", className
, assemblyName
));
857 public Type
ReadType (BinaryReader reader
, TypeTag code
)
859 return ReadType (reader
, code
, true);
862 public Type
ReadType (BinaryReader reader
, TypeTag code
, bool throwOnError
)
866 case TypeTag
.PrimitiveType
:
867 return BinaryCommon
.GetTypeFromCode (reader
.ReadByte());
870 return typeof(string);
872 case TypeTag
.ObjectType
:
873 return typeof(object);
875 case TypeTag
.RuntimeType
:
877 string name
= reader
.ReadString ();
878 // map MS.NET's System.RuntimeType to System.MonoType
879 if (_context
.State
== StreamingContextStates
.Remoting
)
880 if (name
== "System.RuntimeType")
881 return typeof (MonoType
);
882 else if (name
== "System.RuntimeType[]")
883 return typeof (MonoType
[]);
884 Type t
= Type
.GetType (name
);
888 throw new SerializationException (String
.Format ("Could not find type '{0}'.", name
));
891 case TypeTag
.GenericType
:
893 string name
= reader
.ReadString ();
894 long asmid
= (long) reader
.ReadUInt32();
895 return GetDeserializationType (asmid
, name
, throwOnError
);
898 case TypeTag
.ArrayOfObject
:
899 return typeof(object[]);
901 case TypeTag
.ArrayOfString
:
902 return typeof(string[]);
904 case TypeTag
.ArrayOfPrimitiveType
:
905 Type elementType
= BinaryCommon
.GetTypeFromCode (reader
.ReadByte());
906 return Type
.GetType(elementType
.FullName
+ "[]");
909 throw new NotSupportedException ("Unknow type tag");
913 public static object ReadPrimitiveTypeValue (BinaryReader reader
, Type type
)
915 if (type
== null) return null;
917 switch (Type
.GetTypeCode (type
))
919 case TypeCode
.Boolean
:
920 return reader
.ReadBoolean();
923 return reader
.ReadByte();
926 return reader
.ReadChar();
928 case TypeCode
.DateTime
:
929 return DateTime
.FromBinary (reader
.ReadInt64());
931 case TypeCode
.Decimal
:
932 return Decimal
.Parse (reader
.ReadString(), CultureInfo
.InvariantCulture
);
934 case TypeCode
.Double
:
935 return reader
.ReadDouble();
938 return reader
.ReadInt16();
941 return reader
.ReadInt32();
944 return reader
.ReadInt64();
947 return reader
.ReadSByte();
949 case TypeCode
.Single
:
950 return reader
.ReadSingle();
952 case TypeCode
.UInt16
:
953 return reader
.ReadUInt16();
955 case TypeCode
.UInt32
:
956 return reader
.ReadUInt32();
958 case TypeCode
.UInt64
:
959 return reader
.ReadUInt64();
961 case TypeCode
.String
:
962 return reader
.ReadString();
965 if (type
== typeof(TimeSpan
))
966 return new TimeSpan (reader
.ReadInt64 ());
968 throw new NotSupportedException ("Unsupported primitive type: " + type
.FullName
);