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 info = metadata.NeedsSerializationInfo ? new SerializationInfo(metadata.Type, new FormatterConverter()) : null;
\r
268 if (metadata.MemberNames != null)
\r
269 for (int n=0; n<metadata.FieldCount; n++)
\r
270 ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberNames[n], null, null);
\r
272 for (int n=0; n<metadata.FieldCount; n++)
\r
273 ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberInfos[n].Name, metadata.MemberInfos[n], null);
\r
276 private void RegisterObject (long objectId, object objectInstance, SerializationInfo info, long parentObjectId, MemberInfo parentObjectMemeber, int[] indices)
\r
278 if (parentObjectId == 0) indices = null;
\r
280 if (!objectInstance.GetType().IsValueType || parentObjectId == 0)
\r
281 _manager.RegisterObject (objectInstance, objectId, info, 0, null, null);
\r
284 if (indices != null) indices = (int[])indices.Clone();
\r
285 _manager.RegisterObject (objectInstance, objectId, info, parentObjectId, parentObjectMemeber, indices);
\r
289 private void ReadStringIntance (BinaryReader reader, out long objectId, out object value)
\r
291 objectId = (long) reader.ReadUInt32 ();
\r
292 value = reader.ReadString ();
\r
295 private void ReadGenericArray (BinaryReader reader, out long objectId, out object val)
\r
297 objectId = (long) reader.ReadUInt32 ();
\r
301 int rank = reader.ReadInt32();
\r
303 bool emptyDim = false;
\r
304 int[] lengths = new int[rank];
\r
305 for (int n=0; n<rank; n++)
\r
307 lengths[n] = reader.ReadInt32();
\r
308 if (lengths[n] == 0) emptyDim = true;
\r
311 TypeTag code = (TypeTag) reader.ReadByte ();
\r
312 Type elementType = ReadType (reader, code);
\r
314 Array array = Array.CreateInstance (elementType, lengths);
\r
322 int[] indices = new int[rank];
\r
324 // Initialize indexes
\r
325 for (int dim = rank-1; dim >= 0; dim--)
\r
326 indices[dim] = array.GetLowerBound (dim);
\r
331 ReadValue (reader, array, objectId, null, elementType, null, null, indices);
\r
333 for (int dim = array.Rank-1; dim >= 0; dim--)
\r
336 if (indices[dim] > array.GetUpperBound (dim))
\r
340 indices[dim] = array.GetLowerBound (dim);
\r
341 continue; // Increment the next dimension's index
\r
343 end = true; // That was the last dimension. Finished.
\r
351 private object ReadBoxedPrimitiveTypeValue (BinaryReader reader)
\r
353 Type type = ReadType (reader, TypeTag.PrimitiveType);
\r
354 return ReadPrimitiveTypeValue (reader, type);
\r
357 private void ReadArrayOfPrimitiveType (BinaryReader reader, out long objectId, out object val)
\r
359 objectId = (long) reader.ReadUInt32 ();
\r
360 int length = reader.ReadInt32 ();
\r
361 Type elementType = ReadType (reader, TypeTag.PrimitiveType);
\r
363 switch (Type.GetTypeCode (elementType))
\r
365 case TypeCode.Boolean: {
\r
366 bool[] arr = new bool [length];
\r
367 for (int n = 0; n < length; n++) arr [n] = reader.ReadBoolean();
\r
372 case TypeCode.Byte: {
\r
373 byte[] arr = new byte [length];
\r
375 while (pos < length) {
\r
376 int nr = reader.Read (arr, pos, length - pos);
\r
377 if (nr == 0) break;
\r
384 case TypeCode.Char: {
\r
385 char[] arr = new char [length];
\r
387 while (pos < length) {
\r
388 int nr = reader.Read (arr, pos, length - pos);
\r
389 if (nr == 0) break;
\r
396 case TypeCode.DateTime: {
\r
397 DateTime[] arr = new DateTime [length];
\r
398 for (int n = 0; n < length; n++) {
\r
399 ulong nr = reader.ReadUInt64 ();
\r
400 const ulong mask = (1ul << 62) - 1;
\r
401 long ticks = (long) (nr & mask);
\r
403 DateTimeKind kind = (DateTimeKind) (nr >> 62);
\r
404 arr [n] = new DateTime (ticks, kind);
\r
406 arr [n] = new DateTime (ticks);
\r
413 case TypeCode.Decimal: {
\r
414 Decimal[] arr = new Decimal [length];
\r
415 for (int n = 0; n < length; n++) arr [n] = reader.ReadDecimal();
\r
420 case TypeCode.Double: {
\r
421 Double[] arr = new Double [length];
\r
423 BlockRead (reader, arr, 8);
\r
425 for (int n = 0; n < length; n++) arr [n] = reader.ReadDouble();
\r
430 case TypeCode.Int16: {
\r
431 short[] arr = new short [length];
\r
433 BlockRead (reader, arr, 2);
\r
435 for (int n = 0; n < length; n++) arr [n] = reader.ReadInt16();
\r
440 case TypeCode.Int32: {
\r
441 int[] arr = new int [length];
\r
443 BlockRead (reader, arr, 4);
\r
445 for (int n = 0; n < length; n++) arr [n] = reader.ReadInt32();
\r
450 case TypeCode.Int64: {
\r
451 long[] arr = new long [length];
\r
453 BlockRead (reader, arr, 8);
\r
455 for (int n = 0; n < length; n++) arr [n] = reader.ReadInt64();
\r
460 case TypeCode.SByte: {
\r
461 sbyte[] arr = new sbyte [length];
\r
463 BlockRead (reader, arr, 1);
\r
465 for (int n = 0; n < length; n++) arr [n] = reader.ReadSByte();
\r
470 case TypeCode.Single: {
\r
471 float[] arr = new float [length];
\r
473 BlockRead (reader, arr, 4);
\r
475 for (int n = 0; n < length; n++) arr [n] = reader.ReadSingle();
\r
480 case TypeCode.UInt16: {
\r
481 ushort[] arr = new ushort [length];
\r
483 BlockRead (reader, arr, 2);
\r
485 for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt16();
\r
490 case TypeCode.UInt32: {
\r
491 uint[] arr = new uint [length];
\r
493 BlockRead (reader, arr, 4);
\r
495 for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt32();
\r
500 case TypeCode.UInt64: {
\r
501 ulong[] arr = new ulong [length];
\r
503 BlockRead (reader, arr, 8);
\r
505 for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt64();
\r
510 case TypeCode.String: {
\r
511 string[] arr = new string [length];
\r
512 for (int n = 0; n < length; n++) arr [n] = reader.ReadString();
\r
518 if (elementType == typeof(TimeSpan)) {
\r
519 TimeSpan[] arr = new TimeSpan [length];
\r
520 for (int n = 0; n < length; n++) arr [n] = new TimeSpan (reader.ReadInt64 ());
\r
524 throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);
\r
530 private void BlockRead (BinaryReader reader, Array array, int dataSize)
\r
532 int totalSize = Buffer.ByteLength (array);
\r
534 if (arrayBuffer == null || (totalSize > arrayBuffer.Length && arrayBuffer.Length != ArrayBufferLength))
\r
535 arrayBuffer = new byte [totalSize <= ArrayBufferLength ? totalSize : ArrayBufferLength];
\r
538 while (totalSize > 0) {
\r
539 int size = totalSize < arrayBuffer.Length ? totalSize : arrayBuffer.Length;
\r
542 int nr = reader.Read (arrayBuffer, ap, size - ap);
\r
543 if (nr == 0) break;
\r
545 } while (ap < size);
\r
547 if (!BitConverter.IsLittleEndian && dataSize > 1)
\r
548 BinaryCommon.SwapBytes (arrayBuffer, size, dataSize);
\r
550 Buffer.BlockCopy (arrayBuffer, 0, array, pos, size);
\r
557 private void ReadArrayOfObject (BinaryReader reader, out long objectId, out object array)
\r
559 ReadSimpleArray (reader, typeof (object), out objectId, out array);
\r
562 private void ReadArrayOfString (BinaryReader reader, out long objectId, out object array)
\r
564 ReadSimpleArray (reader, typeof (string), out objectId, out array);
\r
567 private void ReadSimpleArray (BinaryReader reader, Type elementType, out long objectId, out object val)
\r
569 objectId = (long) reader.ReadUInt32 ();
\r
570 int length = reader.ReadInt32 ();
\r
571 int[] indices = new int[1];
\r
573 Array array = Array.CreateInstance (elementType, length);
\r
574 for (int n = 0; n < length; n++)
\r
577 ReadValue (reader, array, objectId, null, elementType, null, null, indices);
\r
583 private TypeMetadata ReadTypeMetadata (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo)
\r
585 TypeMetadata metadata = new TypeMetadata();
\r
587 string className = reader.ReadString ();
\r
588 int fieldCount = reader.ReadInt32 ();
\r
590 Type[] types = new Type[fieldCount];
\r
591 string[] names = new string[fieldCount];
\r
593 for (int n=0; n<fieldCount; n++)
\r
594 names [n] = reader.ReadString ();
\r
598 TypeTag[] codes = new TypeTag[fieldCount];
\r
600 for (int n=0; n<fieldCount; n++)
\r
601 codes [n] = (TypeTag) reader.ReadByte ();
\r
603 for (int n=0; n<fieldCount; n++)
\r
604 types [n] = ReadType (reader, codes[n]);
\r
609 if (!isRuntimeObject)
\r
611 long assemblyId = (long)reader.ReadUInt32();
\r
612 metadata.Type = GetDeserializationType (assemblyId, className);
\r
615 metadata.Type = Type.GetType (className, true);
\r
617 metadata.MemberTypes = types;
\r
618 metadata.MemberNames = names;
\r
619 metadata.FieldCount = names.Length;
\r
621 // Now check if this objects needs a SerializationInfo struct for deserialziation.
\r
622 // SerializationInfo is needed if the object has to be deserialized using
\r
623 // a serialization surrogate, or if it implements ISerializable.
\r
625 if (_surrogateSelector != null)
\r
627 // check if the surrogate selector handles objects of the given type.
\r
628 ISurrogateSelector selector;
\r
629 ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (metadata.Type, _context, out selector);
\r
630 metadata.NeedsSerializationInfo = (surrogate != null);
\r
633 if (!metadata.NeedsSerializationInfo)
\r
635 // Check if the object is marked with the Serializable attribute
\r
637 if (!metadata.Type.IsSerializable)
\r
638 throw new SerializationException("Serializable objects must be marked with the Serializable attribute");
\r
640 metadata.NeedsSerializationInfo = (metadata.Type.GetInterface ("ISerializable") != null);
\r
641 if (!metadata.NeedsSerializationInfo)
\r
643 metadata.MemberInfos = new MemberInfo [fieldCount];
\r
644 for (int n=0; n<fieldCount; n++)
\r
646 FieldInfo field = null;
\r
647 string memberName = names[n];
\r
649 int i = memberName.IndexOf ('+');
\r
651 string baseTypeName = names[n].Substring (0,i);
\r
652 memberName = names[n].Substring (i+1);
\r
653 Type t = metadata.Type.BaseType;
\r
654 while (t != null) {
\r
655 if (t.Name == baseTypeName) {
\r
656 field = t.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
\r
664 field = metadata.Type.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
\r
666 if (field == null) throw new SerializationException ("Field \"" + names[n] + "\" not found in class " + metadata.Type.FullName);
\r
667 metadata.MemberInfos [n] = field;
\r
669 if (!hasTypeInfo) {
\r
670 types [n] = field.FieldType;
\r
673 metadata.MemberNames = null; // Info now in MemberInfos
\r
677 // Registers the type's metadata so it can be reused later if
\r
678 // a RefTypeObject element is found
\r
680 if (!_typeMetadataCache.ContainsKey (metadata.Type))
\r
681 _typeMetadataCache [metadata.Type] = metadata;
\r
687 private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices)
\r
689 // Reads a value from the stream and assigns it to the member of an object
\r
693 if (BinaryCommon.IsPrimitive (valueType))
\r
695 val = ReadPrimitiveTypeValue (reader, valueType);
\r
696 SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);
\r
702 BinaryElement element = (BinaryElement)reader.ReadByte ();
\r
704 if (element == BinaryElement.ObjectReference)
\r
706 // Just read the id of the referred object and record a fixup
\r
707 long childObjectId = (long) reader.ReadUInt32();
\r
708 RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices);
\r
713 SerializationInfo objectInfo;
\r
715 ReadObject (element, reader, out objectId, out val, out objectInfo);
\r
717 // There are two cases where the object cannot be assigned to the parent
\r
718 // and a fixup must be used:
\r
719 // 1) When what has been read is not an object, but an id of an object that
\r
720 // has not been read yet (an object reference). This is managed in the
\r
721 // previous block of code.
\r
722 // 2) When the read object is a value type object. Value type fields hold
\r
723 // copies of objects, not references. Thus, if the value object that
\r
724 // has been read has pending fixups, those fixups would be made to the
\r
725 // boxed copy in the ObjectManager, and not in the required object instance
\r
727 // First of all register the fixup, and then the object. ObjectManager is more
\r
728 // efficient if done in this order
\r
730 bool hasFixup = false;
\r
733 if (val.GetType().IsValueType)
\r
735 RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, memberInfo, indices);
\r
739 // Register the value
\r
741 if (info == null && !(parentObject is Array))
\r
742 RegisterObject (objectId, val, objectInfo, parentObjectId, memberInfo, null);
\r
744 RegisterObject (objectId, val, objectInfo, parentObjectId, null, indices);
\r
746 // Assign the value to the parent object, unless there is a fixup
\r
749 SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);
\r
752 private void SetObjectValue (object parentObject, string fieldName, MemberInfo memberInfo, SerializationInfo info, object value, Type valueType, int[] indices)
\r
754 if (value is IObjectReference)
\r
755 value = ((IObjectReference)value).GetRealObject (_context);
\r
757 if (parentObject is Array)
\r
759 if (value is ArrayNullFiller)
\r
761 // It must be a single dimension array of objects.
\r
762 // Just increase the index. Elements are null by default.
\r
763 int count = ((ArrayNullFiller)value).NullCount;
\r
764 indices[0] += count - 1;
\r
767 ((Array)parentObject).SetValue (value, indices);
\r
769 else if (info != null) {
\r
770 info.AddValue (fieldName, value, valueType);
\r
773 if (memberInfo is FieldInfo)
\r
774 ((FieldInfo)memberInfo).SetValue (parentObject, value);
\r
776 ((PropertyInfo)memberInfo).SetValue (parentObject, value, null);
\r
780 private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, MemberInfo memberInfo, int[] indices)
\r
782 if (info != null) {
\r
783 _manager.RecordDelayedFixup (parentObjectId, fieldName, childObjectId);
\r
785 else if (parentObject is Array) {
\r
786 if (indices.Length == 1)
\r
787 _manager.RecordArrayElementFixup (parentObjectId, indices[0], childObjectId);
\r
789 _manager.RecordArrayElementFixup (parentObjectId, (int[])indices.Clone(), childObjectId);
\r
792 _manager.RecordFixup (parentObjectId, memberInfo, childObjectId);
\r
796 private Type GetDeserializationType (long assemblyId, string className)
\r
799 string assemblyName = (string)_registeredAssemblies[assemblyId];
\r
801 if (_binder != null) {
\r
802 t = _binder.BindToType (assemblyName, className);
\r
807 Assembly assembly = Assembly.Load (assemblyName);
\r
808 t = assembly.GetType (className, true);
\r
811 throw new SerializationException ("Couldn't find type '" + className + "'.");
\r
814 public Type ReadType (BinaryReader reader, TypeTag code)
\r
818 case TypeTag.PrimitiveType:
\r
819 return BinaryCommon.GetTypeFromCode (reader.ReadByte());
\r
821 case TypeTag.String:
\r
822 return typeof(string);
\r
824 case TypeTag.ObjectType:
\r
825 return typeof(object);
\r
827 case TypeTag.RuntimeType:
\r
829 string name = reader.ReadString ();
\r
830 return Type.GetType (name, true);
\r
833 case TypeTag.GenericType:
\r
835 string name = reader.ReadString ();
\r
836 long asmid = (long) reader.ReadUInt32();
\r
837 return GetDeserializationType (asmid, name);
\r
840 case TypeTag.ArrayOfObject:
\r
841 return typeof(object[]);
\r
843 case TypeTag.ArrayOfString:
\r
844 return typeof(string[]);
\r
846 case TypeTag.ArrayOfPrimitiveType:
\r
847 Type elementType = BinaryCommon.GetTypeFromCode (reader.ReadByte());
\r
848 return Type.GetType(elementType.FullName + "[]");
\r
851 throw new NotSupportedException ("Unknow type tag");
\r
855 public static object ReadPrimitiveTypeValue (BinaryReader reader, Type type)
\r
857 if (type == null) return null;
\r
859 switch (Type.GetTypeCode (type))
\r
861 case TypeCode.Boolean:
\r
862 return reader.ReadBoolean();
\r
864 case TypeCode.Byte:
\r
865 return reader.ReadByte();
\r
867 case TypeCode.Char:
\r
868 return reader.ReadChar();
\r
870 case TypeCode.DateTime:
\r
871 return new DateTime (reader.ReadInt64());
\r
873 case TypeCode.Decimal:
\r
874 return Decimal.Parse (reader.ReadString(), CultureInfo.InvariantCulture);
\r
876 case TypeCode.Double:
\r
877 return reader.ReadDouble();
\r
879 case TypeCode.Int16:
\r
880 return reader.ReadInt16();
\r
882 case TypeCode.Int32:
\r
883 return reader.ReadInt32();
\r
885 case TypeCode.Int64:
\r
886 return reader.ReadInt64();
\r
888 case TypeCode.SByte:
\r
889 return reader.ReadSByte();
\r
891 case TypeCode.Single:
\r
892 return reader.ReadSingle();
\r
894 case TypeCode.UInt16:
\r
895 return reader.ReadUInt16();
\r
897 case TypeCode.UInt32:
\r
898 return reader.ReadUInt32();
\r
900 case TypeCode.UInt64:
\r
901 return reader.ReadUInt64();
\r
903 case TypeCode.String:
\r
904 return reader.ReadString();
\r
907 if (type == typeof(TimeSpan))
\r
908 return new TimeSpan (reader.ReadInt64 ());
\r
910 throw new NotSupportedException ("Unsupported primitive type: " + type.FullName);
\r