4 // Lluis Sanchez Gual (lluis@ideary.com)
\r
5 // Patrik Torstensson
\r
7 // (C) 2003 Lluis Sanchez Gual
\r
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
\r
12 // Permission is hereby granted, free of charge, to any person obtaining
\r
13 // a copy of this software and associated documentation files (the
\r
14 // "Software"), to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify, merge, publish,
\r
16 // distribute, sublicense, and/or sell copies of the Software, and to
\r
17 // permit persons to whom the Software is furnished to do so, subject to
\r
18 // the following conditions:
\r
20 // The above copyright notice and this permission notice shall be
\r
21 // included in all copies or substantial portions of the Software.
\r
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
33 using System.Runtime.Serialization;
\r
35 using System.Collections;
\r
36 using System.Reflection;
\r
37 using System.Runtime.Remoting.Messaging;
\r
38 using System.Globalization;
\r
40 namespace System.Runtime.Serialization.Formatters.Binary
\r
42 internal class ObjectReader
\r
44 BinaryFormatter _formatter;
\r
45 ISurrogateSelector _surrogateSelector;
\r
46 StreamingContext _context;
\r
47 SerializationBinder _binder;
\r
50 TypeFilterLevel _filterLevel;
\r
53 ObjectManager _manager;
\r
54 Hashtable _registeredAssemblies = new Hashtable();
\r
55 Hashtable _typeMetadataCache = new Hashtable();
\r
57 object _lastObject = null;
\r
58 long _lastObjectID = 0;
\r
59 long _rootObjectID = 0;
\r
61 int ArrayBufferLength = 4096;
\r
66 public Type[] MemberTypes;
\r
67 public string[] MemberNames;
\r
68 public MemberInfo[] MemberInfos;
\r
69 public int FieldCount;
\r
70 public bool NeedsSerializationInfo;
\r
73 class ArrayNullFiller
\r
75 public ArrayNullFiller(int count) { NullCount = count; }
\r
76 public int NullCount;
\r
79 public ObjectReader (BinaryFormatter formatter)
\r
81 _formatter = formatter;
\r
82 _surrogateSelector = formatter.SurrogateSelector;
\r
83 _context = formatter.Context;
\r
84 _binder = formatter.Binder;
\r
85 _manager = new ObjectManager (_surrogateSelector, _context);
\r
88 _filterLevel = formatter.FilterLevel;
\r
92 public void ReadObjectGraph (BinaryReader reader, bool readHeaders, out object result, out Header[] headers)
\r
96 // Reads the objects. The first object in the stream is the
\r
99 while (ReadNextObject (reader))
\r
101 if (readHeaders && (headers == null))
\r
102 headers = (Header[])CurrentObject;
\r
104 if (_rootObjectID == 0) _rootObjectID = _lastObjectID;
\r
107 result = _manager.GetObject (_rootObjectID);
\r
110 public bool ReadNextObject (BinaryReader reader)
\r
112 BinaryElement element = (BinaryElement)reader.ReadByte ();
\r
113 if (element == BinaryElement.End)
\r
115 _manager.DoFixups();
\r
117 _manager.RaiseDeserializationEvent();
\r
121 SerializationInfo info;
\r
124 ReadObject (element, reader, out objectId, out _lastObject, out info);
\r
126 if (objectId != 0) {
\r
127 RegisterObject (objectId, _lastObject, info, 0, null, null);
\r
128 _lastObjectID = objectId;
\r
134 public object CurrentObject
\r
136 get { return _lastObject; }
\r
139 // Reads an object from the stream. The object is registered in the ObjectManager.
\r
140 // The result can be either the object instance
\r
141 // or the id of the object (when what is found in the stream is an object reference).
\r
142 // If an object instance is read, the objectId is set to 0.
\r
144 private void ReadObject (BinaryElement element, BinaryReader reader, out long objectId, out object value, out SerializationInfo info)
\r
148 case BinaryElement.RefTypeObject:
\r
149 ReadRefTypeObjectInstance (reader, out objectId, out value, out info);
\r
152 case BinaryElement.UntypedRuntimeObject:
\r
153 ReadObjectInstance (reader, true, false, out objectId, out value, out info);
\r
156 case BinaryElement.UntypedExternalObject:
\r
157 ReadObjectInstance (reader, false, false, out objectId, out value, out info);
\r
160 case BinaryElement.RuntimeObject:
\r
161 ReadObjectInstance (reader, true, true, out objectId, out value, out info);
\r
164 case BinaryElement.ExternalObject:
\r
165 ReadObjectInstance (reader, false, true, out objectId, out value, out info);
\r
168 case BinaryElement.String:
\r
170 ReadStringIntance (reader, out objectId, out value);
\r
173 case BinaryElement.GenericArray:
\r
175 ReadGenericArray (reader, out objectId, out value);
\r
179 case BinaryElement.BoxedPrimitiveTypeValue:
\r
180 value = ReadBoxedPrimitiveTypeValue (reader);
\r
185 case BinaryElement.NullValue:
\r
191 case BinaryElement.Assembly:
\r
192 ReadAssembly (reader);
\r
193 ReadObject ((BinaryElement)reader.ReadByte (), reader, out objectId, out value, out info);
\r
196 case BinaryElement.ArrayFiller8b:
\r
197 value = new ArrayNullFiller(reader.ReadByte());
\r
202 case BinaryElement.ArrayFiller32b:
\r
203 value = new ArrayNullFiller(reader.ReadInt32());
\r
208 case BinaryElement.ArrayOfPrimitiveType:
\r
209 ReadArrayOfPrimitiveType (reader, out objectId, out value);
\r
213 case BinaryElement.ArrayOfObject:
\r
214 ReadArrayOfObject (reader, out objectId, out value);
\r
218 case BinaryElement.ArrayOfString:
\r
219 ReadArrayOfString (reader, out objectId, out value);
\r
224 throw new SerializationException ("Unexpected binary element: " + (int)element);
\r
228 private void ReadAssembly (BinaryReader reader)
\r
230 long id = (long) reader.ReadUInt32 ();
\r
231 string assemblyName = reader.ReadString ();
\r
232 _registeredAssemblies [id] = assemblyName;
\r
235 private void ReadObjectInstance (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo, out long objectId, out object value, out SerializationInfo info)
\r
237 objectId = (long) reader.ReadUInt32 ();
\r
239 TypeMetadata metadata = ReadTypeMetadata (reader, isRuntimeObject, hasTypeInfo);
\r
240 ReadObjectContent (reader, metadata, objectId, out value, out info);
\r
243 private void ReadRefTypeObjectInstance (BinaryReader reader, out long objectId, out object value, out SerializationInfo info)
\r
245 objectId = (long) reader.ReadUInt32 ();
\r
246 long refTypeObjectId = (long) reader.ReadUInt32 ();
\r
248 // Gets the type of the referred object and its metadata
\r
250 object refObj = _manager.GetObject (refTypeObjectId);
\r
251 if (refObj == null) throw new SerializationException ("Invalid binary format");
\r
252 TypeMetadata metadata = (TypeMetadata)_typeMetadataCache [refObj.GetType()];
\r
254 ReadObjectContent (reader, metadata, objectId, out value, out info);
\r
257 private void ReadObjectContent (BinaryReader reader, TypeMetadata metadata, long objectId, out object objectInstance, out SerializationInfo info)
\r
260 if (_filterLevel == TypeFilterLevel.Low)
\r
261 objectInstance = FormatterServices.GetSafeUninitializedObject (metadata.Type);
\r
264 objectInstance = FormatterServices.GetUninitializedObject (metadata.Type);
\r
266 _manager.RaiseOnDeserializingEvent (objectInstance);
269 info = metadata.NeedsSerializationInfo ? new SerializationInfo(metadata.Type, new FormatterConverter()) : null;
\r
271 if (metadata.MemberNames != null)
\r
272 for (int n=0; n<metadata.FieldCount; n++)
\r
273 ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberNames[n], null, null);
\r
275 for (int n=0; n<metadata.FieldCount; n++)
\r
276 ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberInfos[n].Name, metadata.MemberInfos[n], null);
\r
279 private void RegisterObject (long objectId, object objectInstance, SerializationInfo info, long parentObjectId, MemberInfo parentObjectMemeber, int[] indices)
\r
281 if (parentObjectId == 0) indices = null;
\r
283 if (!objectInstance.GetType().IsValueType || parentObjectId == 0)
\r
284 _manager.RegisterObject (objectInstance, objectId, info, 0, null, null);
\r
287 if (indices != null) indices = (int[])indices.Clone();
\r
288 _manager.RegisterObject (objectInstance, objectId, info, parentObjectId, parentObjectMemeber, indices);
\r
292 private void ReadStringIntance (BinaryReader reader, out long objectId, out object value)
\r
294 objectId = (long) reader.ReadUInt32 ();
\r
295 value = reader.ReadString ();
\r
298 private void ReadGenericArray (BinaryReader reader, out long objectId, out object val)
\r
300 objectId = (long) reader.ReadUInt32 ();
\r
304 int rank = reader.ReadInt32();
\r
306 bool emptyDim = false;
\r
307 int[] lengths = new int[rank];
\r
308 for (int n=0; n<rank; n++)
\r
310 lengths[n] = reader.ReadInt32();
\r
311 if (lengths[n] == 0) emptyDim = true;
\r
314 TypeTag code = (TypeTag) reader.ReadByte ();
\r
315 Type elementType = ReadType (reader, code);
\r
317 Array array = Array.CreateInstance (elementType, lengths);
\r
325 int[] indices = new int[rank];
\r
327 // Initialize indexes
\r
328 for (int dim = rank-1; dim >= 0; dim--)
\r
329 indices[dim] = array.GetLowerBound (dim);
\r
334 ReadValue (reader, array, objectId, null, elementType, null, null, indices);
\r
336 for (int dim = array.Rank-1; dim >= 0; dim--)
\r
339 if (indices[dim] > array.GetUpperBound (dim))
\r
343 indices[dim] = array.GetLowerBound (dim);
\r
344 continue; // Increment the next dimension's index
\r
346 end = true; // That was the last dimension. Finished.
\r
354 private object ReadBoxedPrimitiveTypeValue (BinaryReader reader)
\r
356 Type type = ReadType (reader, TypeTag.PrimitiveType);
\r
357 return ReadPrimitiveTypeValue (reader, type);
\r
360 private void ReadArrayOfPrimitiveType (BinaryReader reader, out long objectId, out object val)
\r
362 objectId = (long) reader.ReadUInt32 ();
\r
363 int length = reader.ReadInt32 ();
\r
364 Type elementType = ReadType (reader, TypeTag.PrimitiveType);
\r
366 switch (Type.GetTypeCode (elementType))
\r
368 case TypeCode.Boolean: {
\r
369 bool[] arr = new bool [length];
\r
370 for (int n = 0; n < length; n++) arr [n] = reader.ReadBoolean();
\r
375 case TypeCode.Byte: {
\r
376 byte[] arr = new byte [length];
\r
378 while (pos < length) {
\r
379 int nr = reader.Read (arr, pos, length - pos);
\r
380 if (nr == 0) break;
\r
387 case TypeCode.Char: {
\r
388 char[] arr = new char [length];
\r
390 while (pos < length) {
\r
391 int nr = reader.Read (arr, pos, length - pos);
\r
392 if (nr == 0) break;
\r
399 case TypeCode.DateTime: {
\r
400 DateTime[] arr = new DateTime [length];
\r
401 for (int n = 0; n < length; n++) {
\r
402 ulong nr = reader.ReadUInt64 ();
\r
403 const ulong mask = (1ul << 62) - 1;
\r
404 long ticks = (long) (nr & mask);
\r
406 DateTimeKind kind = (DateTimeKind) (nr >> 62);
\r
407 arr [n] = new DateTime (ticks, kind);
\r
409 arr [n] = new DateTime (ticks);
\r
416 case TypeCode.Decimal: {
\r
417 Decimal[] arr = new Decimal [length];
\r
418 for (int n = 0; n < length; n++) arr [n] = reader.ReadDecimal();
\r
423 case TypeCode.Double: {
\r
424 Double[] arr = new Double [length];
\r
426 BlockRead (reader, arr, 8);
\r
428 for (int n = 0; n < length; n++) arr [n] = reader.ReadDouble();
\r
433 case TypeCode.Int16: {
\r
434 short[] arr = new short [length];
\r
436 BlockRead (reader, arr, 2);
\r
438 for (int n = 0; n < length; n++) arr [n] = reader.ReadInt16();
\r
443 case TypeCode.Int32: {
\r
444 int[] arr = new int [length];
\r
446 BlockRead (reader, arr, 4);
\r
448 for (int n = 0; n < length; n++) arr [n] = reader.ReadInt32();
\r
453 case TypeCode.Int64: {
\r
454 long[] arr = new long [length];
\r
456 BlockRead (reader, arr, 8);
\r
458 for (int n = 0; n < length; n++) arr [n] = reader.ReadInt64();
\r
463 case TypeCode.SByte: {
\r
464 sbyte[] arr = new sbyte [length];
\r
466 BlockRead (reader, arr, 1);
\r
468 for (int n = 0; n < length; n++) arr [n] = reader.ReadSByte();
\r
473 case TypeCode.Single: {
\r
474 float[] arr = new float [length];
\r
476 BlockRead (reader, arr, 4);
\r
478 for (int n = 0; n < length; n++) arr [n] = reader.ReadSingle();
\r
483 case TypeCode.UInt16: {
\r
484 ushort[] arr = new ushort [length];
\r
486 BlockRead (reader, arr, 2);
\r
488 for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt16();
\r
493 case TypeCode.UInt32: {
\r
494 uint[] arr = new uint [length];
\r
496 BlockRead (reader, arr, 4);
\r
498 for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt32();
\r
503 case TypeCode.UInt64: {
\r
504 ulong[] arr = new ulong [length];
\r
506 BlockRead (reader, arr, 8);
\r
508 for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt64();
\r
513 case TypeCode.String: {
\r
514 string[] arr = new string [length];
\r
515 for (int n = 0; n < length; n++) arr [n] = reader.ReadString();
\r
521 if (elementType == typeof(TimeSpan)) {
\r
522 TimeSpan[] arr = new TimeSpan [length];
\r
523 for (int n = 0; n < length; n++) arr [n] = new TimeSpan (reader.ReadInt64 ());
\r
527 throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);
\r
533 private void BlockRead (BinaryReader reader, Array array, int dataSize)
\r
535 int totalSize = Buffer.ByteLength (array);
\r
537 if (arrayBuffer == null || (totalSize > arrayBuffer.Length && arrayBuffer.Length != ArrayBufferLength))
\r
538 arrayBuffer = new byte [totalSize <= ArrayBufferLength ? totalSize : ArrayBufferLength];
\r
541 while (totalSize > 0) {
\r
542 int size = totalSize < arrayBuffer.Length ? totalSize : arrayBuffer.Length;
\r
545 int nr = reader.Read (arrayBuffer, ap, size - ap);
\r
546 if (nr == 0) break;
\r
548 } while (ap < size);
\r
550 if (!BitConverter.IsLittleEndian && dataSize > 1)
\r
551 BinaryCommon.SwapBytes (arrayBuffer, size, dataSize);
\r
553 Buffer.BlockCopy (arrayBuffer, 0, array, pos, size);
\r
560 private void ReadArrayOfObject (BinaryReader reader, out long objectId, out object array)
\r
562 ReadSimpleArray (reader, typeof (object), out objectId, out array);
\r
565 private void ReadArrayOfString (BinaryReader reader, out long objectId, out object array)
\r
567 ReadSimpleArray (reader, typeof (string), out objectId, out array);
\r
570 private void ReadSimpleArray (BinaryReader reader, Type elementType, out long objectId, out object val)
\r
572 objectId = (long) reader.ReadUInt32 ();
\r
573 int length = reader.ReadInt32 ();
\r
574 int[] indices = new int[1];
\r
576 Array array = Array.CreateInstance (elementType, length);
\r
577 for (int n = 0; n < length; n++)
\r
580 ReadValue (reader, array, objectId, null, elementType, null, null, indices);
\r
586 private TypeMetadata ReadTypeMetadata (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo)
\r
588 TypeMetadata metadata = new TypeMetadata();
\r
590 string className = reader.ReadString ();
\r
591 int fieldCount = reader.ReadInt32 ();
\r
593 Type[] types = new Type[fieldCount];
\r
594 string[] names = new string[fieldCount];
\r
596 for (int n=0; n<fieldCount; n++)
\r
597 names [n] = reader.ReadString ();
\r
601 TypeTag[] codes = new TypeTag[fieldCount];
\r
603 for (int n=0; n<fieldCount; n++)
\r
604 codes [n] = (TypeTag) reader.ReadByte ();
\r
606 for (int n=0; n<fieldCount; n++)
\r
607 types [n] = ReadType (reader, codes[n]);
\r
612 if (!isRuntimeObject)
\r
614 long assemblyId = (long)reader.ReadUInt32();
\r
615 metadata.Type = GetDeserializationType (assemblyId, className);
\r
618 metadata.Type = Type.GetType (className, true);
\r
620 metadata.MemberTypes = types;
\r
621 metadata.MemberNames = names;
\r
622 metadata.FieldCount = names.Length;
\r
624 // Now check if this objects needs a SerializationInfo struct for deserialziation.
\r
625 // SerializationInfo is needed if the object has to be deserialized using
\r
626 // a serialization surrogate, or if it implements ISerializable.
\r
628 if (_surrogateSelector != null)
\r
630 // check if the surrogate selector handles objects of the given type.
\r
631 ISurrogateSelector selector;
\r
632 ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (metadata.Type, _context, out selector);
\r
633 metadata.NeedsSerializationInfo = (surrogate != null);
\r
636 if (!metadata.NeedsSerializationInfo)
\r
638 // Check if the object is marked with the Serializable attribute
\r
640 if (!metadata.Type.IsSerializable)
\r
641 throw new SerializationException("Serializable objects must be marked with the Serializable attribute");
\r
643 metadata.NeedsSerializationInfo = (metadata.Type.GetInterface ("ISerializable") != null);
\r
644 if (!metadata.NeedsSerializationInfo)
\r
646 metadata.MemberInfos = new MemberInfo [fieldCount];
\r
647 for (int n=0; n<fieldCount; n++)
\r
649 FieldInfo field = null;
\r
650 string memberName = names[n];
\r
652 int i = memberName.IndexOf ('+');
\r
654 string baseTypeName = names[n].Substring (0,i);
\r
655 memberName = names[n].Substring (i+1);
\r
656 Type t = metadata.Type.BaseType;
\r
657 while (t != null) {
\r
658 if (t.Name == baseTypeName) {
\r
659 field = t.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
\r
667 field = metadata.Type.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
\r
669 if (field == null) throw new SerializationException ("Field \"" + names[n] + "\" not found in class " + metadata.Type.FullName);
\r
670 metadata.MemberInfos [n] = field;
\r
672 if (!hasTypeInfo) {
\r
673 types [n] = field.FieldType;
\r
676 metadata.MemberNames = null; // Info now in MemberInfos
\r
680 // Registers the type's metadata so it can be reused later if
\r
681 // a RefTypeObject element is found
\r
683 if (!_typeMetadataCache.ContainsKey (metadata.Type))
\r
684 _typeMetadataCache [metadata.Type] = metadata;
\r
690 private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices)
\r
692 // Reads a value from the stream and assigns it to the member of an object
\r
696 if (BinaryCommon.IsPrimitive (valueType))
\r
698 val = ReadPrimitiveTypeValue (reader, valueType);
\r
699 SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);
\r
705 BinaryElement element = (BinaryElement)reader.ReadByte ();
\r
707 if (element == BinaryElement.ObjectReference)
\r
709 // Just read the id of the referred object and record a fixup
\r
710 long childObjectId = (long) reader.ReadUInt32();
\r
711 RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices);
\r
716 SerializationInfo objectInfo;
\r
718 ReadObject (element, reader, out objectId, out val, out objectInfo);
\r
720 // There are two cases where the object cannot be assigned to the parent
\r
721 // and a fixup must be used:
\r
722 // 1) When what has been read is not an object, but an id of an object that
\r
723 // has not been read yet (an object reference). This is managed in the
\r
724 // previous block of code.
\r
725 // 2) When the read object is a value type object. Value type fields hold
\r
726 // copies of objects, not references. Thus, if the value object that
\r
727 // has been read has pending fixups, those fixups would be made to the
\r
728 // boxed copy in the ObjectManager, and not in the required object instance
\r
730 // First of all register the fixup, and then the object. ObjectManager is more
\r
731 // efficient if done in this order
\r
733 bool hasFixup = false;
\r
736 if (val.GetType().IsValueType)
\r
738 RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, memberInfo, indices);
\r
742 // Register the value
\r
744 if (info == null && !(parentObject is Array))
\r
745 RegisterObject (objectId, val, objectInfo, parentObjectId, memberInfo, null);
\r
747 RegisterObject (objectId, val, objectInfo, parentObjectId, null, indices);
\r
749 // Assign the value to the parent object, unless there is a fixup
\r
752 SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);
\r
755 private void SetObjectValue (object parentObject, string fieldName, MemberInfo memberInfo, SerializationInfo info, object value, Type valueType, int[] indices)
\r
757 if (value is IObjectReference)
\r
758 value = ((IObjectReference)value).GetRealObject (_context);
\r
760 if (parentObject is Array)
\r
762 if (value is ArrayNullFiller)
\r
764 // It must be a single dimension array of objects.
\r
765 // Just increase the index. Elements are null by default.
\r
766 int count = ((ArrayNullFiller)value).NullCount;
\r
767 indices[0] += count - 1;
\r
770 ((Array)parentObject).SetValue (value, indices);
\r
772 else if (info != null) {
\r
773 info.AddValue (fieldName, value, valueType);
\r
776 if (memberInfo is FieldInfo)
\r
777 ((FieldInfo)memberInfo).SetValue (parentObject, value);
\r
779 ((PropertyInfo)memberInfo).SetValue (parentObject, value, null);
\r
783 private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, MemberInfo memberInfo, int[] indices)
\r
785 if (info != null) {
\r
786 _manager.RecordDelayedFixup (parentObjectId, fieldName, childObjectId);
\r
788 else if (parentObject is Array) {
\r
789 if (indices.Length == 1)
\r
790 _manager.RecordArrayElementFixup (parentObjectId, indices[0], childObjectId);
\r
792 _manager.RecordArrayElementFixup (parentObjectId, (int[])indices.Clone(), childObjectId);
\r
795 _manager.RecordFixup (parentObjectId, memberInfo, childObjectId);
\r
799 private Type GetDeserializationType (long assemblyId, string className)
\r
802 string assemblyName = (string)_registeredAssemblies[assemblyId];
\r
804 if (_binder != null) {
\r
805 t = _binder.BindToType (assemblyName, className);
\r
810 Assembly assembly = Assembly.Load (assemblyName);
\r
811 t = assembly.GetType (className, true);
\r
814 throw new SerializationException ("Couldn't find type '" + className + "'.");
\r
817 public Type ReadType (BinaryReader reader, TypeTag code)
\r
821 case TypeTag.PrimitiveType:
\r
822 return BinaryCommon.GetTypeFromCode (reader.ReadByte());
\r
824 case TypeTag.String:
\r
825 return typeof(string);
\r
827 case TypeTag.ObjectType:
\r
828 return typeof(object);
\r
830 case TypeTag.RuntimeType:
\r
832 string name = reader.ReadString ();
\r
833 return Type.GetType (name, true);
\r
836 case TypeTag.GenericType:
\r
838 string name = reader.ReadString ();
\r
839 long asmid = (long) reader.ReadUInt32();
\r
840 return GetDeserializationType (asmid, name);
\r
843 case TypeTag.ArrayOfObject:
\r
844 return typeof(object[]);
\r
846 case TypeTag.ArrayOfString:
\r
847 return typeof(string[]);
\r
849 case TypeTag.ArrayOfPrimitiveType:
\r
850 Type elementType = BinaryCommon.GetTypeFromCode (reader.ReadByte());
\r
851 return Type.GetType(elementType.FullName + "[]");
\r
854 throw new NotSupportedException ("Unknow type tag");
\r
858 public static object ReadPrimitiveTypeValue (BinaryReader reader, Type type)
\r
860 if (type == null) return null;
\r
862 switch (Type.GetTypeCode (type))
\r
864 case TypeCode.Boolean:
\r
865 return reader.ReadBoolean();
\r
867 case TypeCode.Byte:
\r
868 return reader.ReadByte();
\r
870 case TypeCode.Char:
\r
871 return reader.ReadChar();
\r
873 case TypeCode.DateTime:
\r
874 return new DateTime (reader.ReadInt64());
\r
876 case TypeCode.Decimal:
\r
877 return Decimal.Parse (reader.ReadString(), CultureInfo.InvariantCulture);
\r
879 case TypeCode.Double:
\r
880 return reader.ReadDouble();
\r
882 case TypeCode.Int16:
\r
883 return reader.ReadInt16();
\r
885 case TypeCode.Int32:
\r
886 return reader.ReadInt32();
\r
888 case TypeCode.Int64:
\r
889 return reader.ReadInt64();
\r
891 case TypeCode.SByte:
\r
892 return reader.ReadSByte();
\r
894 case TypeCode.Single:
\r
895 return reader.ReadSingle();
\r
897 case TypeCode.UInt16:
\r
898 return reader.ReadUInt16();
\r
900 case TypeCode.UInt32:
\r
901 return reader.ReadUInt32();
\r
903 case TypeCode.UInt64:
\r
904 return reader.ReadUInt64();
\r
906 case TypeCode.String:
\r
907 return reader.ReadString();
\r
910 if (type == typeof(TimeSpan))
\r
911 return new TimeSpan (reader.ReadInt64 ());
\r
913 throw new NotSupportedException ("Unsupported primitive type: " + type.FullName);
\r