ObjectReader.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. // ObjectReader.cs
  2. //
  3. // Author:
  4. // Lluis Sanchez Gual ([email protected])
  5. // Patrik Torstensson
  6. //
  7. // (C) 2003 Lluis Sanchez Gual
  8. //
  9. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. using System;
  31. using System.Runtime.Serialization;
  32. using System.IO;
  33. using System.Collections;
  34. using System.Reflection;
  35. using System.Runtime.Remoting.Messaging;
  36. using System.Globalization;
  37. namespace System.Runtime.Serialization.Formatters.Binary
  38. {
  39. internal class ObjectReader
  40. {
  41. // BinaryFormatter _formatter;
  42. ISurrogateSelector _surrogateSelector;
  43. StreamingContext _context;
  44. SerializationBinder _binder;
  45. TypeFilterLevel _filterLevel;
  46. ObjectManager _manager;
  47. Hashtable _registeredAssemblies = new Hashtable();
  48. Hashtable _typeMetadataCache = new Hashtable();
  49. object _lastObject = null;
  50. long _lastObjectID = 0;
  51. long _rootObjectID = 0;
  52. byte[] arrayBuffer;
  53. int ArrayBufferLength = 4096;
  54. class TypeMetadata
  55. {
  56. public Type Type;
  57. public Type[] MemberTypes;
  58. public string[] MemberNames;
  59. public MemberInfo[] MemberInfos;
  60. public int FieldCount;
  61. public bool NeedsSerializationInfo;
  62. }
  63. class ArrayNullFiller
  64. {
  65. public ArrayNullFiller(int count) { NullCount = count; }
  66. public int NullCount;
  67. }
  68. public ObjectReader (BinaryFormatter formatter)
  69. {
  70. // _formatter = formatter;
  71. _surrogateSelector = formatter.SurrogateSelector;
  72. _context = formatter.Context;
  73. _binder = formatter.Binder;
  74. _manager = new ObjectManager (_surrogateSelector, _context);
  75. _filterLevel = formatter.FilterLevel;
  76. }
  77. public void ReadObjectGraph (BinaryReader reader, bool readHeaders, out object result, out Header[] headers)
  78. {
  79. BinaryElement elem = (BinaryElement)reader.ReadByte ();
  80. ReadObjectGraph (elem, reader, readHeaders, out result, out headers);
  81. }
  82. public void ReadObjectGraph (BinaryElement elem, BinaryReader reader, bool readHeaders, out object result, out Header[] headers)
  83. {
  84. headers = null;
  85. // Reads the objects. The first object in the stream is the
  86. // root object.
  87. bool next = ReadNextObject (elem, reader);
  88. if (next) {
  89. do {
  90. if (readHeaders && (headers == null))
  91. headers = (Header[])CurrentObject;
  92. else
  93. if (_rootObjectID == 0) _rootObjectID = _lastObjectID;
  94. } while (ReadNextObject (reader));
  95. }
  96. result = _manager.GetObject (_rootObjectID);
  97. }
  98. bool ReadNextObject (BinaryElement element, BinaryReader reader)
  99. {
  100. if (element == BinaryElement.End)
  101. {
  102. _manager.DoFixups();
  103. _manager.RaiseDeserializationEvent();
  104. return false;
  105. }
  106. SerializationInfo info;
  107. long objectId;
  108. ReadObject (element, reader, out objectId, out _lastObject, out info);
  109. if (objectId != 0) {
  110. RegisterObject (objectId, _lastObject, info, 0, null, null);
  111. _lastObjectID = objectId;
  112. }
  113. return true;
  114. }
  115. public bool ReadNextObject (BinaryReader reader)
  116. {
  117. BinaryElement element = (BinaryElement)reader.ReadByte ();
  118. if (element == BinaryElement.End)
  119. {
  120. _manager.DoFixups();
  121. _manager.RaiseDeserializationEvent();
  122. return false;
  123. }
  124. SerializationInfo info;
  125. long objectId;
  126. ReadObject (element, reader, out objectId, out _lastObject, out info);
  127. if (objectId != 0) {
  128. RegisterObject (objectId, _lastObject, info, 0, null, null);
  129. _lastObjectID = objectId;
  130. }
  131. return true;
  132. }
  133. public object CurrentObject
  134. {
  135. get { return _lastObject; }
  136. }
  137. // Reads an object from the stream. The object is registered in the ObjectManager.
  138. // The result can be either the object instance
  139. // or the id of the object (when what is found in the stream is an object reference).
  140. // If an object instance is read, the objectId is set to 0.
  141. private void ReadObject (BinaryElement element, BinaryReader reader, out long objectId, out object value, out SerializationInfo info)
  142. {
  143. switch (element)
  144. {
  145. case BinaryElement.RefTypeObject:
  146. ReadRefTypeObjectInstance (reader, out objectId, out value, out info);
  147. break;
  148. case BinaryElement.UntypedRuntimeObject:
  149. ReadObjectInstance (reader, true, false, out objectId, out value, out info);
  150. break;
  151. case BinaryElement.UntypedExternalObject:
  152. ReadObjectInstance (reader, false, false, out objectId, out value, out info);
  153. break;
  154. case BinaryElement.RuntimeObject:
  155. ReadObjectInstance (reader, true, true, out objectId, out value, out info);
  156. break;
  157. case BinaryElement.ExternalObject:
  158. ReadObjectInstance (reader, false, true, out objectId, out value, out info);
  159. break;
  160. case BinaryElement.String:
  161. info = null;
  162. ReadStringIntance (reader, out objectId, out value);
  163. break;
  164. case BinaryElement.GenericArray:
  165. info = null;
  166. ReadGenericArray (reader, out objectId, out value);
  167. break;
  168. case BinaryElement.BoxedPrimitiveTypeValue:
  169. value = ReadBoxedPrimitiveTypeValue (reader);
  170. objectId = 0;
  171. info = null;
  172. break;
  173. case BinaryElement.NullValue:
  174. value = null;
  175. objectId = 0;
  176. info = null;
  177. break;
  178. case BinaryElement.Assembly:
  179. ReadAssembly (reader);
  180. ReadObject ((BinaryElement)reader.ReadByte (), reader, out objectId, out value, out info);
  181. break;
  182. case BinaryElement.ArrayFiller8b:
  183. value = new ArrayNullFiller(reader.ReadByte());
  184. objectId = 0;
  185. info = null;
  186. break;
  187. case BinaryElement.ArrayFiller32b:
  188. value = new ArrayNullFiller(reader.ReadInt32());
  189. objectId = 0;
  190. info = null;
  191. break;
  192. case BinaryElement.ArrayOfPrimitiveType:
  193. ReadArrayOfPrimitiveType (reader, out objectId, out value);
  194. info = null;
  195. break;
  196. case BinaryElement.ArrayOfObject:
  197. ReadArrayOfObject (reader, out objectId, out value);
  198. info = null;
  199. break;
  200. case BinaryElement.ArrayOfString:
  201. ReadArrayOfString (reader, out objectId, out value);
  202. info = null;
  203. break;
  204. default:
  205. throw new SerializationException ("Unexpected binary element: " + (int)element);
  206. }
  207. }
  208. private void ReadAssembly (BinaryReader reader)
  209. {
  210. long id = (long) reader.ReadUInt32 ();
  211. string assemblyName = reader.ReadString ();
  212. _registeredAssemblies [id] = assemblyName;
  213. }
  214. private void ReadObjectInstance (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo, out long objectId, out object value, out SerializationInfo info)
  215. {
  216. objectId = (long) reader.ReadUInt32 ();
  217. TypeMetadata metadata = ReadTypeMetadata (reader, isRuntimeObject, hasTypeInfo);
  218. ReadObjectContent (reader, metadata, objectId, out value, out info);
  219. }
  220. private void ReadRefTypeObjectInstance (BinaryReader reader, out long objectId, out object value, out SerializationInfo info)
  221. {
  222. objectId = (long) reader.ReadUInt32 ();
  223. long refTypeObjectId = (long) reader.ReadUInt32 ();
  224. // Gets the type of the referred object and its metadata
  225. object refObj = _manager.GetObject (refTypeObjectId);
  226. if (refObj == null) throw new SerializationException ("Invalid binary format");
  227. TypeMetadata metadata = (TypeMetadata)_typeMetadataCache [refObj.GetType()];
  228. ReadObjectContent (reader, metadata, objectId, out value, out info);
  229. }
  230. private void ReadObjectContent (BinaryReader reader, TypeMetadata metadata, long objectId, out object objectInstance, out SerializationInfo info)
  231. {
  232. if (_filterLevel == TypeFilterLevel.Low)
  233. objectInstance = FormatterServices.GetSafeUninitializedObject (metadata.Type);
  234. else
  235. objectInstance = FormatterServices.GetUninitializedObject (metadata.Type);
  236. _manager.RaiseOnDeserializingEvent (objectInstance);
  237. info = metadata.NeedsSerializationInfo ? new SerializationInfo(metadata.Type, new FormatterConverter()) : null;
  238. if (metadata.MemberNames != null) {
  239. for (int n=0; n<metadata.FieldCount; n++)
  240. ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberNames[n], null, null);
  241. } else
  242. for (int n=0; n<metadata.FieldCount; n++) {
  243. if (metadata.MemberInfos [n] != null)
  244. ReadValue (reader, objectInstance, objectId, info, metadata.MemberTypes[n], metadata.MemberInfos[n].Name, metadata.MemberInfos[n], null);
  245. else if (BinaryCommon.IsPrimitive(metadata.MemberTypes[n])) {
  246. // Since the member info is null, the type in this
  247. // domain does not have this type. Even though we
  248. // are not going to store the value, we will read
  249. // it from the stream so that we can advance to the
  250. // next block.
  251. ReadPrimitiveTypeValue (reader, metadata.MemberTypes[n]);
  252. }
  253. }
  254. }
  255. private void RegisterObject (long objectId, object objectInstance, SerializationInfo info, long parentObjectId, MemberInfo parentObjectMemeber, int[] indices)
  256. {
  257. if (parentObjectId == 0) indices = null;
  258. if (!objectInstance.GetType().IsValueType || parentObjectId == 0)
  259. _manager.RegisterObject (objectInstance, objectId, info, 0, null, null);
  260. else
  261. {
  262. if (indices != null) indices = (int[])indices.Clone();
  263. _manager.RegisterObject (objectInstance, objectId, info, parentObjectId, parentObjectMemeber, indices);
  264. }
  265. }
  266. private void ReadStringIntance (BinaryReader reader, out long objectId, out object value)
  267. {
  268. objectId = (long) reader.ReadUInt32 ();
  269. value = reader.ReadString ();
  270. }
  271. private void ReadGenericArray (BinaryReader reader, out long objectId, out object val)
  272. {
  273. objectId = (long) reader.ReadUInt32 ();
  274. // Array structure
  275. reader.ReadByte();
  276. int rank = reader.ReadInt32();
  277. bool emptyDim = false;
  278. int[] lengths = new int[rank];
  279. for (int n=0; n<rank; n++)
  280. {
  281. lengths[n] = reader.ReadInt32();
  282. if (lengths[n] == 0) emptyDim = true;
  283. }
  284. TypeTag code = (TypeTag) reader.ReadByte ();
  285. Type elementType = ReadType (reader, code);
  286. Array array = Array.CreateInstance (elementType, lengths);
  287. if (emptyDim)
  288. {
  289. val = array;
  290. return;
  291. }
  292. int[] indices = new int[rank];
  293. // Initialize indexes
  294. for (int dim = rank-1; dim >= 0; dim--)
  295. indices[dim] = array.GetLowerBound (dim);
  296. bool end = false;
  297. while (!end)
  298. {
  299. ReadValue (reader, array, objectId, null, elementType, null, null, indices);
  300. for (int dim = array.Rank-1; dim >= 0; dim--)
  301. {
  302. indices[dim]++;
  303. if (indices[dim] > array.GetUpperBound (dim))
  304. {
  305. if (dim > 0)
  306. {
  307. indices[dim] = array.GetLowerBound (dim);
  308. continue; // Increment the next dimension's index
  309. }
  310. end = true; // That was the last dimension. Finished.
  311. }
  312. break;
  313. }
  314. }
  315. val = array;
  316. }
  317. private object ReadBoxedPrimitiveTypeValue (BinaryReader reader)
  318. {
  319. Type type = ReadType (reader, TypeTag.PrimitiveType);
  320. return ReadPrimitiveTypeValue (reader, type);
  321. }
  322. private void ReadArrayOfPrimitiveType (BinaryReader reader, out long objectId, out object val)
  323. {
  324. objectId = (long) reader.ReadUInt32 ();
  325. int length = reader.ReadInt32 ();
  326. Type elementType = ReadType (reader, TypeTag.PrimitiveType);
  327. switch (Type.GetTypeCode (elementType))
  328. {
  329. case TypeCode.Boolean: {
  330. bool[] arr = new bool [length];
  331. for (int n = 0; n < length; n++) arr [n] = reader.ReadBoolean();
  332. val = arr;
  333. break;
  334. }
  335. case TypeCode.Byte: {
  336. byte[] arr = new byte [length];
  337. int pos = 0;
  338. while (pos < length) {
  339. int nr = reader.Read (arr, pos, length - pos);
  340. if (nr == 0) break;
  341. pos += nr;
  342. }
  343. val = arr;
  344. break;
  345. }
  346. case TypeCode.Char: {
  347. char[] arr = new char [length];
  348. int pos = 0;
  349. while (pos < length) {
  350. int nr = reader.Read (arr, pos, length - pos);
  351. if (nr == 0) break;
  352. pos += nr;
  353. }
  354. val = arr;
  355. break;
  356. }
  357. case TypeCode.DateTime: {
  358. DateTime[] arr = new DateTime [length];
  359. for (int n = 0; n < length; n++) {
  360. arr [n] = DateTime.FromBinary (reader.ReadInt64 ());
  361. }
  362. val = arr;
  363. break;
  364. }
  365. case TypeCode.Decimal: {
  366. Decimal[] arr = new Decimal [length];
  367. for (int n = 0; n < length; n++) arr [n] = reader.ReadDecimal();
  368. val = arr;
  369. break;
  370. }
  371. case TypeCode.Double: {
  372. Double[] arr = new Double [length];
  373. if (length > 2)
  374. BlockRead (reader, arr, 8);
  375. else
  376. for (int n = 0; n < length; n++) arr [n] = reader.ReadDouble();
  377. val = arr;
  378. break;
  379. }
  380. case TypeCode.Int16: {
  381. short[] arr = new short [length];
  382. if (length > 2)
  383. BlockRead (reader, arr, 2);
  384. else
  385. for (int n = 0; n < length; n++) arr [n] = reader.ReadInt16();
  386. val = arr;
  387. break;
  388. }
  389. case TypeCode.Int32: {
  390. int[] arr = new int [length];
  391. if (length > 2)
  392. BlockRead (reader, arr, 4);
  393. else
  394. for (int n = 0; n < length; n++) arr [n] = reader.ReadInt32();
  395. val = arr;
  396. break;
  397. }
  398. case TypeCode.Int64: {
  399. long[] arr = new long [length];
  400. if (length > 2)
  401. BlockRead (reader, arr, 8);
  402. else
  403. for (int n = 0; n < length; n++) arr [n] = reader.ReadInt64();
  404. val = arr;
  405. break;
  406. }
  407. case TypeCode.SByte: {
  408. sbyte[] arr = new sbyte [length];
  409. if (length > 2)
  410. BlockRead (reader, arr, 1);
  411. else
  412. for (int n = 0; n < length; n++) arr [n] = reader.ReadSByte();
  413. val = arr;
  414. break;
  415. }
  416. case TypeCode.Single: {
  417. float[] arr = new float [length];
  418. if (length > 2)
  419. BlockRead (reader, arr, 4);
  420. else
  421. for (int n = 0; n < length; n++) arr [n] = reader.ReadSingle();
  422. val = arr;
  423. break;
  424. }
  425. case TypeCode.UInt16: {
  426. ushort[] arr = new ushort [length];
  427. if (length > 2)
  428. BlockRead (reader, arr, 2);
  429. else
  430. for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt16();
  431. val = arr;
  432. break;
  433. }
  434. case TypeCode.UInt32: {
  435. uint[] arr = new uint [length];
  436. if (length > 2)
  437. BlockRead (reader, arr, 4);
  438. else
  439. for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt32();
  440. val = arr;
  441. break;
  442. }
  443. case TypeCode.UInt64: {
  444. ulong[] arr = new ulong [length];
  445. if (length > 2)
  446. BlockRead (reader, arr, 8);
  447. else
  448. for (int n = 0; n < length; n++) arr [n] = reader.ReadUInt64();
  449. val = arr;
  450. break;
  451. }
  452. case TypeCode.String: {
  453. string[] arr = new string [length];
  454. for (int n = 0; n < length; n++) arr [n] = reader.ReadString();
  455. val = arr;
  456. break;
  457. }
  458. default: {
  459. if (elementType == typeof(TimeSpan)) {
  460. TimeSpan[] arr = new TimeSpan [length];
  461. for (int n = 0; n < length; n++) arr [n] = new TimeSpan (reader.ReadInt64 ());
  462. val = arr;
  463. }
  464. else
  465. throw new NotSupportedException ("Unsupported primitive type: " + elementType.FullName);
  466. break;
  467. }
  468. }
  469. }
  470. private void BlockRead (BinaryReader reader, Array array, int dataSize)
  471. {
  472. int totalSize = Buffer.ByteLength (array);
  473. if (arrayBuffer == null || (totalSize > arrayBuffer.Length && arrayBuffer.Length != ArrayBufferLength))
  474. arrayBuffer = new byte [totalSize <= ArrayBufferLength ? totalSize : ArrayBufferLength];
  475. int pos = 0;
  476. while (totalSize > 0) {
  477. int size = totalSize < arrayBuffer.Length ? totalSize : arrayBuffer.Length;
  478. int ap = 0;
  479. do {
  480. int nr = reader.Read (arrayBuffer, ap, size - ap);
  481. if (nr == 0) break;
  482. ap += nr;
  483. } while (ap < size);
  484. if (!BitConverter.IsLittleEndian && dataSize > 1)
  485. BinaryCommon.SwapBytes (arrayBuffer, size, dataSize);
  486. Buffer.BlockCopy (arrayBuffer, 0, array, pos, size);
  487. totalSize -= size;
  488. pos += size;
  489. }
  490. }
  491. private void ReadArrayOfObject (BinaryReader reader, out long objectId, out object array)
  492. {
  493. ReadSimpleArray (reader, typeof (object), out objectId, out array);
  494. }
  495. private void ReadArrayOfString (BinaryReader reader, out long objectId, out object array)
  496. {
  497. ReadSimpleArray (reader, typeof (string), out objectId, out array);
  498. }
  499. private void ReadSimpleArray (BinaryReader reader, Type elementType, out long objectId, out object val)
  500. {
  501. objectId = (long) reader.ReadUInt32 ();
  502. int length = reader.ReadInt32 ();
  503. int[] indices = new int[1];
  504. Array array = Array.CreateInstance (elementType, length);
  505. for (int n = 0; n < length; n++)
  506. {
  507. indices[0] = n;
  508. ReadValue (reader, array, objectId, null, elementType, null, null, indices);
  509. n = indices[0];
  510. }
  511. val = array;
  512. }
  513. private TypeMetadata ReadTypeMetadata (BinaryReader reader, bool isRuntimeObject, bool hasTypeInfo)
  514. {
  515. TypeMetadata metadata = new TypeMetadata();
  516. string className = reader.ReadString ();
  517. int fieldCount = reader.ReadInt32 ();
  518. Type[] types = new Type[fieldCount];
  519. string[] names = new string[fieldCount];
  520. for (int n=0; n<fieldCount; n++)
  521. names [n] = reader.ReadString ();
  522. if (hasTypeInfo)
  523. {
  524. TypeTag[] codes = new TypeTag[fieldCount];
  525. for (int n=0; n<fieldCount; n++)
  526. codes [n] = (TypeTag) reader.ReadByte ();
  527. for (int n=0; n<fieldCount; n++) {
  528. Type t = ReadType (reader, codes[n], false);
  529. // The field's type could not be resolved: assume it is an object.
  530. if (t == null)
  531. t = typeof (object);
  532. types [n] = t;
  533. }
  534. }
  535. // Gets the type
  536. if (!isRuntimeObject)
  537. {
  538. long assemblyId = (long)reader.ReadUInt32();
  539. metadata.Type = GetDeserializationType (assemblyId, className);
  540. }
  541. else
  542. metadata.Type = Type.GetType (className, true);
  543. metadata.MemberTypes = types;
  544. metadata.MemberNames = names;
  545. metadata.FieldCount = names.Length;
  546. // Now check if this objects needs a SerializationInfo struct for deserialziation.
  547. // SerializationInfo is needed if the object has to be deserialized using
  548. // a serialization surrogate, or if it implements ISerializable.
  549. if (_surrogateSelector != null)
  550. {
  551. // check if the surrogate selector handles objects of the given type.
  552. ISurrogateSelector selector;
  553. ISerializationSurrogate surrogate = _surrogateSelector.GetSurrogate (metadata.Type, _context, out selector);
  554. metadata.NeedsSerializationInfo = (surrogate != null);
  555. }
  556. if (!metadata.NeedsSerializationInfo)
  557. {
  558. // Check if the object is marked with the Serializable attribute
  559. if (!metadata.Type.IsSerializable)
  560. throw new SerializationException("Serializable objects must be marked with the Serializable attribute");
  561. metadata.NeedsSerializationInfo = typeof (ISerializable).IsAssignableFrom (metadata.Type);
  562. if (!metadata.NeedsSerializationInfo)
  563. {
  564. metadata.MemberInfos = new MemberInfo [fieldCount];
  565. for (int n=0; n<fieldCount; n++)
  566. {
  567. FieldInfo field = null;
  568. string memberName = names[n];
  569. int i = memberName.IndexOf ('+');
  570. if (i != -1) {
  571. string baseTypeName = names[n].Substring (0,i);
  572. memberName = names[n].Substring (i+1);
  573. Type t = metadata.Type.BaseType;
  574. while (t != null) {
  575. if (t.Name == baseTypeName) {
  576. field = t.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  577. break;
  578. }
  579. else
  580. t = t.BaseType;
  581. }
  582. }
  583. else
  584. field = metadata.Type.GetField (memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  585. if (field != null)
  586. metadata.MemberInfos [n] = field;
  587. if (!hasTypeInfo) {
  588. types [n] = field.FieldType;
  589. }
  590. }
  591. metadata.MemberNames = null; // Info now in MemberInfos
  592. }
  593. }
  594. // Registers the type's metadata so it can be reused later if
  595. // a RefTypeObject element is found
  596. if (!_typeMetadataCache.ContainsKey (metadata.Type))
  597. _typeMetadataCache [metadata.Type] = metadata;
  598. return metadata;
  599. }
  600. // Called for primitive types
  601. static bool IsGeneric (MemberInfo minfo)
  602. {
  603. if (minfo == null)
  604. return false;
  605. Type mtype = null;
  606. switch (minfo.MemberType) {
  607. case MemberTypes.Field:
  608. mtype = ((FieldInfo) minfo).FieldType;
  609. break;
  610. default:
  611. throw new NotSupportedException ("Not supported: " + minfo.MemberType);
  612. }
  613. return (mtype != null && mtype.IsGenericType);
  614. }
  615. private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices)
  616. {
  617. // Reads a value from the stream and assigns it to the member of an object
  618. object val;
  619. if (BinaryCommon.IsPrimitive (valueType) && !IsGeneric (memberInfo))
  620. {
  621. val = ReadPrimitiveTypeValue (reader, valueType);
  622. SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);
  623. return;
  624. }
  625. // Gets the object
  626. BinaryElement element = (BinaryElement)reader.ReadByte ();
  627. if (element == BinaryElement.ObjectReference)
  628. {
  629. // Just read the id of the referred object and record a fixup
  630. long childObjectId = (long) reader.ReadUInt32();
  631. RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices);
  632. return;
  633. }
  634. long objectId;
  635. SerializationInfo objectInfo;
  636. ReadObject (element, reader, out objectId, out val, out objectInfo);
  637. // There are two cases where the object cannot be assigned to the parent
  638. // and a fixup must be used:
  639. // 1) When what has been read is not an object, but an id of an object that
  640. // has not been read yet (an object reference). This is managed in the
  641. // previous block of code.
  642. // 2) When the read object is a value type object. Value type fields hold
  643. // copies of objects, not references. Thus, if the value object that
  644. // has been read has pending fixups, those fixups would be made to the
  645. // boxed copy in the ObjectManager, and not in the required object instance
  646. // First of all register the fixup, and then the object. ObjectManager is more
  647. // efficient if done in this order
  648. bool hasFixup = false;
  649. if (objectId != 0)
  650. {
  651. if (val.GetType().IsValueType)
  652. {
  653. RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, memberInfo, indices);
  654. hasFixup = true;
  655. }
  656. // Register the value
  657. if (info == null && !(parentObject is Array))
  658. RegisterObject (objectId, val, objectInfo, parentObjectId, memberInfo, null);
  659. else
  660. RegisterObject (objectId, val, objectInfo, parentObjectId, null, indices);
  661. }
  662. // Assign the value to the parent object, unless there is a fixup
  663. if (!hasFixup)
  664. SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices);
  665. }
  666. private void SetObjectValue (object parentObject, string fieldName, MemberInfo memberInfo, SerializationInfo info, object value, Type valueType, int[] indices)
  667. {
  668. if (value is IObjectReference)
  669. value = ((IObjectReference)value).GetRealObject (_context);
  670. if (parentObject is Array)
  671. {
  672. if (value is ArrayNullFiller)
  673. {
  674. // It must be a single dimension array of objects.
  675. // Just increase the index. Elements are null by default.
  676. int count = ((ArrayNullFiller)value).NullCount;
  677. indices[0] += count - 1;
  678. }
  679. else
  680. ((Array)parentObject).SetValue (value, indices);
  681. }
  682. else if (info != null) {
  683. info.AddValue (fieldName, value, valueType);
  684. }
  685. else {
  686. if (memberInfo is FieldInfo)
  687. ((FieldInfo)memberInfo).SetValue (parentObject, value);
  688. else
  689. ((PropertyInfo)memberInfo).SetValue (parentObject, value, null);
  690. }
  691. }
  692. private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, MemberInfo memberInfo, int[] indices)
  693. {
  694. if (info != null) {
  695. _manager.RecordDelayedFixup (parentObjectId, fieldName, childObjectId);
  696. }
  697. else if (parentObject is Array) {
  698. if (indices.Length == 1)
  699. _manager.RecordArrayElementFixup (parentObjectId, indices[0], childObjectId);
  700. else
  701. _manager.RecordArrayElementFixup (parentObjectId, (int[])indices.Clone(), childObjectId);
  702. }
  703. else {
  704. _manager.RecordFixup (parentObjectId, memberInfo, childObjectId);
  705. }
  706. }
  707. private Type GetDeserializationType (long assemblyId, string className)
  708. {
  709. return GetDeserializationType (assemblyId, className, true);
  710. }
  711. private Type GetDeserializationType (long assemblyId, string className, bool throwOnError)
  712. {
  713. Type t;
  714. string assemblyName = (string)_registeredAssemblies[assemblyId];
  715. if (_binder != null) {
  716. t = _binder.BindToType (assemblyName, className);
  717. if (t != null)
  718. return t;
  719. }
  720. Assembly assembly;
  721. try {
  722. assembly = Assembly.Load (assemblyName);
  723. } catch (Exception ex) {
  724. if (!throwOnError)
  725. return null;
  726. throw new SerializationException (String.Format ("Couldn't find assembly '{0}'", assemblyName), ex);
  727. }
  728. t = assembly.GetType (className);
  729. if (t != null)
  730. return t;
  731. if (!throwOnError)
  732. return null;
  733. throw new SerializationException (String.Format ("Couldn't find type '{0}' in assembly '{1}'", className, assemblyName));
  734. }
  735. public Type ReadType (BinaryReader reader, TypeTag code)
  736. {
  737. return ReadType (reader, code, true);
  738. }
  739. public Type ReadType (BinaryReader reader, TypeTag code, bool throwOnError)
  740. {
  741. switch (code)
  742. {
  743. case TypeTag.PrimitiveType:
  744. return BinaryCommon.GetTypeFromCode (reader.ReadByte());
  745. case TypeTag.String:
  746. return typeof(string);
  747. case TypeTag.ObjectType:
  748. return typeof(object);
  749. case TypeTag.RuntimeType:
  750. {
  751. string name = reader.ReadString ();
  752. // map MS.NET's System.RuntimeType to System.MonoType
  753. if (_context.State == StreamingContextStates.Remoting)
  754. if (name == "System.RuntimeType")
  755. return typeof (MonoType);
  756. else if (name == "System.RuntimeType[]")
  757. return typeof (MonoType[]);
  758. Type t = Type.GetType (name);
  759. if (t != null)
  760. return t;
  761. throw new SerializationException (String.Format ("Could not find type '{0}'.", name));
  762. }
  763. case TypeTag.GenericType:
  764. {
  765. string name = reader.ReadString ();
  766. long asmid = (long) reader.ReadUInt32();
  767. return GetDeserializationType (asmid, name, throwOnError);
  768. }
  769. case TypeTag.ArrayOfObject:
  770. return typeof(object[]);
  771. case TypeTag.ArrayOfString:
  772. return typeof(string[]);
  773. case TypeTag.ArrayOfPrimitiveType:
  774. Type elementType = BinaryCommon.GetTypeFromCode (reader.ReadByte());
  775. return Type.GetType(elementType.FullName + "[]");
  776. default:
  777. throw new NotSupportedException ("Unknow type tag");
  778. }
  779. }
  780. public static object ReadPrimitiveTypeValue (BinaryReader reader, Type type)
  781. {
  782. if (type == null) return null;
  783. switch (Type.GetTypeCode (type))
  784. {
  785. case TypeCode.Boolean:
  786. return reader.ReadBoolean();
  787. case TypeCode.Byte:
  788. return reader.ReadByte();
  789. case TypeCode.Char:
  790. return reader.ReadChar();
  791. case TypeCode.DateTime:
  792. return DateTime.FromBinary (reader.ReadInt64());
  793. case TypeCode.Decimal:
  794. return Decimal.Parse (reader.ReadString(), CultureInfo.InvariantCulture);
  795. case TypeCode.Double:
  796. return reader.ReadDouble();
  797. case TypeCode.Int16:
  798. return reader.ReadInt16();
  799. case TypeCode.Int32:
  800. return reader.ReadInt32();
  801. case TypeCode.Int64:
  802. return reader.ReadInt64();
  803. case TypeCode.SByte:
  804. return reader.ReadSByte();
  805. case TypeCode.Single:
  806. return reader.ReadSingle();
  807. case TypeCode.UInt16:
  808. return reader.ReadUInt16();
  809. case TypeCode.UInt32:
  810. return reader.ReadUInt32();
  811. case TypeCode.UInt64:
  812. return reader.ReadUInt64();
  813. case TypeCode.String:
  814. return reader.ReadString();
  815. default:
  816. if (type == typeof(TimeSpan))
  817. return new TimeSpan (reader.ReadInt64 ());
  818. else
  819. throw new NotSupportedException ("Unsupported primitive type: " + type.FullName);
  820. }
  821. }
  822. }
  823. }