ObjectManager.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. //
  2. // System.Runtime.Serialization.ObjectManager.cs
  3. //
  4. // Author: Lluis Sanchez Gual ([email protected])
  5. //
  6. // (C) 2003 Lluis Sanchez Gual
  7. //
  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.Collections;
  32. using System.Reflection;
  33. namespace System.Runtime.Serialization
  34. {
  35. [System.Runtime.InteropServices.ComVisibleAttribute (true)]
  36. public class ObjectManager
  37. {
  38. // All objects are chained in the same order as they have been registered
  39. ObjectRecord _objectRecordChain = null;
  40. ObjectRecord _lastObjectRecord = null;
  41. ArrayList _deserializedRecords = new ArrayList();
  42. ArrayList _onDeserializedCallbackRecords = new ArrayList();
  43. Hashtable _objectRecords = new Hashtable();
  44. bool _finalFixup = false;
  45. ISurrogateSelector _selector;
  46. StreamingContext _context;
  47. int _registeredObjectsCount = 0;
  48. public ObjectManager(ISurrogateSelector selector, StreamingContext context)
  49. {
  50. _selector = selector;
  51. _context = context;
  52. }
  53. public virtual void DoFixups()
  54. {
  55. _finalFixup = true;
  56. try
  57. {
  58. if (_registeredObjectsCount < _objectRecords.Count)
  59. throw new SerializationException ("There are some fixups that refer to objects that have not been registered");
  60. ObjectRecord last = _lastObjectRecord;
  61. bool firstCycle = true;
  62. bool lastCycle = false;
  63. int unresolvedCount = 0; // Unresolved objects found in the current cycle
  64. int lastUnresolvedCount = 0; // Unresolved objects before the current cycle
  65. // Solve al pending fixups of all objects
  66. ObjectRecord record = _objectRecordChain;
  67. while (record != null)
  68. {
  69. // We ignore object references in the first cycle
  70. bool ready = !(record.IsUnsolvedObjectReference && firstCycle);
  71. if (ready) ready = record.DoFixups (true, this, true);
  72. if (ready) ready = record.LoadData(this, _selector, _context);
  73. ObjectRecord next;
  74. if (ready)
  75. {
  76. if (record.OriginalObject is IDeserializationCallback)
  77. _deserializedRecords.Add (record);
  78. SerializationCallbacks sc = SerializationCallbacks
  79. .GetSerializationCallbacks (record.OriginalObject.GetType ());
  80. if (sc.HasDeserializedCallbacks)
  81. _onDeserializedCallbackRecords.Add (record);
  82. next = record.Next;
  83. }
  84. else
  85. {
  86. // There must be an unresolved IObjectReference instance.
  87. // Chain the record at the end so it is solved later
  88. if ((record.ObjectInstance is IObjectReference) && !firstCycle)
  89. {
  90. if (record.IsUnsolvedObjectReference && lastCycle)
  91. // No more chances to resolve
  92. throw new SerializationException ("The object with ID " + record.ObjectID + " could not be resolved");
  93. else {
  94. unresolvedCount++;
  95. }
  96. }
  97. if (record != _lastObjectRecord) {
  98. next = record.Next;
  99. record.Next = null;
  100. _lastObjectRecord.Next = record;
  101. _lastObjectRecord = record;
  102. }
  103. else
  104. next = record;
  105. }
  106. if (record == last) {
  107. last = _lastObjectRecord;
  108. if (firstCycle)
  109. firstCycle = false;
  110. else {
  111. if (lastUnresolvedCount == unresolvedCount)
  112. lastCycle = true;
  113. }
  114. lastUnresolvedCount = unresolvedCount;
  115. unresolvedCount = 0;
  116. }
  117. record = next;
  118. }
  119. }
  120. finally
  121. {
  122. _finalFixup = false;
  123. }
  124. }
  125. internal ObjectRecord GetObjectRecord (long objectID)
  126. {
  127. ObjectRecord rec = (ObjectRecord)_objectRecords[objectID];
  128. if (rec == null)
  129. {
  130. if (_finalFixup) throw new SerializationException ("The object with Id " + objectID + " has not been registered");
  131. rec = new ObjectRecord();
  132. rec.ObjectID = objectID;
  133. _objectRecords[objectID] = rec;
  134. }
  135. if (!rec.IsRegistered && _finalFixup) throw new SerializationException ("The object with Id " + objectID + " has not been registered");
  136. return rec;
  137. }
  138. public virtual object GetObject (long objectID)
  139. {
  140. if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
  141. ObjectRecord rec = (ObjectRecord)_objectRecords[objectID];
  142. if (rec == null || !rec.IsRegistered) return null;
  143. else return rec.ObjectInstance;
  144. }
  145. public virtual void RaiseDeserializationEvent ()
  146. {
  147. for (int i = _onDeserializedCallbackRecords.Count-1; i >= 0; i--)
  148. {
  149. ObjectRecord record = (ObjectRecord) _onDeserializedCallbackRecords [i];
  150. RaiseOnDeserializedEvent (record.OriginalObject);
  151. }
  152. for (int i = _deserializedRecords.Count-1; i >= 0; i--)
  153. {
  154. ObjectRecord record = (ObjectRecord) _deserializedRecords [i];
  155. IDeserializationCallback obj = record.OriginalObject as IDeserializationCallback;
  156. if (obj != null) obj.OnDeserialization (this);
  157. }
  158. }
  159. public void RaiseOnDeserializingEvent (object obj)
  160. {
  161. SerializationCallbacks sc = SerializationCallbacks
  162. .GetSerializationCallbacks (obj.GetType ());
  163. sc.RaiseOnDeserializing (obj, _context);
  164. }
  165. void RaiseOnDeserializedEvent (object obj)
  166. {
  167. SerializationCallbacks sc = SerializationCallbacks
  168. .GetSerializationCallbacks (obj.GetType ());
  169. sc.RaiseOnDeserialized (obj, _context);
  170. }
  171. private void AddFixup (BaseFixupRecord record)
  172. {
  173. record.ObjectToBeFixed.ChainFixup (record, true);
  174. record.ObjectRequired.ChainFixup (record, false);
  175. }
  176. public virtual void RecordArrayElementFixup (long arrayToBeFixed, int index, long objectRequired)
  177. {
  178. if (arrayToBeFixed <= 0) throw new ArgumentOutOfRangeException("arrayToBeFixed","The arrayToBeFixed parameter is less than or equal to zero");
  179. if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
  180. ArrayFixupRecord record = new ArrayFixupRecord(GetObjectRecord(arrayToBeFixed), index, GetObjectRecord(objectRequired));
  181. AddFixup (record);
  182. }
  183. public virtual void RecordArrayElementFixup (long arrayToBeFixed, int[] indices, long objectRequired)
  184. {
  185. if (arrayToBeFixed <= 0) throw new ArgumentOutOfRangeException("arrayToBeFixed","The arrayToBeFixed parameter is less than or equal to zero");
  186. if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
  187. if (indices == null) throw new ArgumentNullException("indices");
  188. MultiArrayFixupRecord record = new MultiArrayFixupRecord (GetObjectRecord(arrayToBeFixed), indices, GetObjectRecord(objectRequired));
  189. AddFixup (record);
  190. }
  191. public virtual void RecordDelayedFixup (long objectToBeFixed, string memberName, long objectRequired)
  192. {
  193. if (objectToBeFixed <= 0) throw new ArgumentOutOfRangeException("objectToBeFixed","The objectToBeFixed parameter is less than or equal to zero");
  194. if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
  195. if (memberName == null) throw new ArgumentNullException("memberName");
  196. DelayedFixupRecord record = new DelayedFixupRecord (GetObjectRecord(objectToBeFixed), memberName, GetObjectRecord(objectRequired));
  197. AddFixup (record);
  198. }
  199. public virtual void RecordFixup (long objectToBeFixed, MemberInfo member, long objectRequired)
  200. {
  201. if (objectToBeFixed <= 0) throw new ArgumentOutOfRangeException("objectToBeFixed","The objectToBeFixed parameter is less than or equal to zero");
  202. if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
  203. if (member == null) throw new ArgumentNullException("member");
  204. FixupRecord record = new FixupRecord (GetObjectRecord(objectToBeFixed), member, GetObjectRecord(objectRequired));
  205. AddFixup (record);
  206. }
  207. private void RegisterObjectInternal (object obj, ObjectRecord record)
  208. {
  209. if (obj == null) throw new ArgumentNullException("obj");
  210. if (record.IsRegistered)
  211. {
  212. if (record.OriginalObject != obj) throw new SerializationException ("An object with Id " + record.ObjectID + " has already been registered");
  213. else return;
  214. }
  215. record.ObjectInstance = obj;
  216. record.OriginalObject = obj;
  217. if (obj is IObjectReference) record.Status = ObjectRecordStatus.ReferenceUnsolved;
  218. else record.Status = ObjectRecordStatus.ReferenceSolved;
  219. if (_selector != null) {
  220. record.Surrogate = _selector.GetSurrogate (
  221. obj.GetType(), _context, out record.SurrogateSelector);
  222. if (record.Surrogate != null)
  223. record.Status = ObjectRecordStatus.ReferenceUnsolved;
  224. }
  225. record.DoFixups (true, this, false);
  226. record.DoFixups (false, this, false);
  227. _registeredObjectsCount++;
  228. // Adds the object to the chain of registered objects. This chain
  229. // is needed to be able to to perform the final fixups in the right order
  230. if (_objectRecordChain == null)
  231. {
  232. _objectRecordChain = record;
  233. _lastObjectRecord = record;
  234. }
  235. else
  236. {
  237. _lastObjectRecord.Next = record;
  238. _lastObjectRecord = record;
  239. }
  240. }
  241. public virtual void RegisterObject (object obj, long objectID)
  242. {
  243. if (obj == null) throw new ArgumentNullException("obj", "The obj parameter is null.");
  244. if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
  245. RegisterObjectInternal (obj, GetObjectRecord (objectID));
  246. }
  247. public void RegisterObject (object obj, long objectID, SerializationInfo info)
  248. {
  249. if (obj == null) throw new ArgumentNullException("obj", "The obj parameter is null.");
  250. if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
  251. ObjectRecord record = GetObjectRecord (objectID);
  252. record.Info = info;
  253. RegisterObjectInternal (obj, record);
  254. }
  255. public void RegisterObject (object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member)
  256. {
  257. RegisterObject (obj, objectID, info, idOfContainingObj, member, null);
  258. }
  259. public void RegisterObject( object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member, int[] arrayIndex)
  260. {
  261. if (obj == null) throw new ArgumentNullException("obj", "The obj parameter is null.");
  262. if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
  263. ObjectRecord record = GetObjectRecord (objectID);
  264. record.Info = info;
  265. record.IdOfContainingObj = idOfContainingObj;
  266. record.Member = member;
  267. record.ArrayIndex = arrayIndex;
  268. RegisterObjectInternal (obj, record);
  269. }
  270. }
  271. // Fixup types. There is a fixup class for each fixup type.
  272. // BaseFixupRecord
  273. // Base class for all fixups
  274. internal abstract class BaseFixupRecord
  275. {
  276. public BaseFixupRecord(ObjectRecord objectToBeFixed, ObjectRecord objectRequired)
  277. {
  278. ObjectToBeFixed = objectToBeFixed;
  279. ObjectRequired = objectRequired;
  280. }
  281. public bool DoFixup (ObjectManager manager, bool strict)
  282. {
  283. if (ObjectToBeFixed.IsRegistered && ObjectRequired.IsInstanceReady)
  284. {
  285. FixupImpl (manager);
  286. return true;
  287. }
  288. else if (strict)
  289. {
  290. if (!ObjectToBeFixed.IsRegistered) throw new SerializationException ("An object with ID " + ObjectToBeFixed.ObjectID + " was included in a fixup, but it has not been registered");
  291. else if (!ObjectRequired.IsRegistered) throw new SerializationException ("An object with ID " + ObjectRequired.ObjectID + " was included in a fixup, but it has not been registered");
  292. else return false;
  293. }
  294. else
  295. return false;
  296. }
  297. protected abstract void FixupImpl (ObjectManager manager);
  298. internal protected ObjectRecord ObjectToBeFixed;
  299. internal protected ObjectRecord ObjectRequired;
  300. public BaseFixupRecord NextSameContainer;
  301. public BaseFixupRecord NextSameRequired;
  302. }
  303. // ArrayFixupRecord
  304. // Fixup for assigning a value to one position of an array
  305. internal class ArrayFixupRecord : BaseFixupRecord
  306. {
  307. int _index;
  308. public ArrayFixupRecord (ObjectRecord objectToBeFixed, int index, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
  309. _index = index;
  310. }
  311. protected override void FixupImpl (ObjectManager manager) {
  312. Array array = (Array)ObjectToBeFixed.ObjectInstance;
  313. array.SetValue (ObjectRequired.ObjectInstance, _index);
  314. }
  315. }
  316. // MultiArrayFixupRecord
  317. // Fixup for assigning a value to several positions of an array
  318. internal class MultiArrayFixupRecord : BaseFixupRecord
  319. {
  320. int[] _indices;
  321. public MultiArrayFixupRecord (ObjectRecord objectToBeFixed, int[] indices, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
  322. _indices = indices;
  323. }
  324. protected override void FixupImpl (ObjectManager manager) {
  325. ObjectToBeFixed.SetArrayValue (manager, ObjectRequired.ObjectInstance, _indices);
  326. }
  327. }
  328. // FixupRecord
  329. // Fixup for assigning a value to a member of an object
  330. internal class FixupRecord: BaseFixupRecord
  331. {
  332. public MemberInfo _member;
  333. public FixupRecord (ObjectRecord objectToBeFixed, MemberInfo member, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
  334. _member = member;
  335. }
  336. protected override void FixupImpl (ObjectManager manager) {
  337. ObjectToBeFixed.SetMemberValue (manager, _member, ObjectRequired.ObjectInstance);
  338. }
  339. }
  340. // DelayedFixupRecord
  341. // Fixup for assigning a value to a SerializationInfo of an object
  342. internal class DelayedFixupRecord: BaseFixupRecord
  343. {
  344. public string _memberName;
  345. public DelayedFixupRecord (ObjectRecord objectToBeFixed, string memberName, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
  346. _memberName = memberName;
  347. }
  348. protected override void FixupImpl (ObjectManager manager) {
  349. ObjectToBeFixed.SetMemberValue (manager, _memberName, ObjectRequired.ObjectInstance);
  350. }
  351. }
  352. // Object Record
  353. internal enum ObjectRecordStatus: byte { Unregistered, ReferenceUnsolved, ReferenceSolved }
  354. internal class ObjectRecord
  355. {
  356. public ObjectRecordStatus Status = ObjectRecordStatus.Unregistered;
  357. public object OriginalObject;
  358. public object ObjectInstance;
  359. public long ObjectID;
  360. public SerializationInfo Info;
  361. public long IdOfContainingObj;
  362. public ISerializationSurrogate Surrogate;
  363. public ISurrogateSelector SurrogateSelector;
  364. public MemberInfo Member;
  365. public int[] ArrayIndex;
  366. public BaseFixupRecord FixupChainAsContainer;
  367. public BaseFixupRecord FixupChainAsRequired;
  368. public ObjectRecord Next;
  369. public void SetMemberValue (ObjectManager manager, MemberInfo member, object value)
  370. {
  371. if (member is FieldInfo)
  372. ((FieldInfo)member).SetValue (ObjectInstance, value);
  373. else if (member is PropertyInfo)
  374. ((PropertyInfo)member).SetValue (ObjectInstance, value, null);
  375. else throw new SerializationException ("Cannot perform fixup");
  376. if (Member != null)
  377. {
  378. ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
  379. if (containerRecord.IsRegistered)
  380. containerRecord.SetMemberValue (manager, Member, ObjectInstance);
  381. }
  382. else if (ArrayIndex != null)
  383. {
  384. ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
  385. if (containerRecord.IsRegistered)
  386. containerRecord.SetArrayValue (manager, ObjectInstance, ArrayIndex);
  387. }
  388. }
  389. public void SetArrayValue (ObjectManager manager, object value, int[] indices)
  390. {
  391. ((Array)ObjectInstance).SetValue (value, indices);
  392. }
  393. public void SetMemberValue (ObjectManager manager, string memberName, object value)
  394. {
  395. if (Info == null) throw new SerializationException ("Cannot perform fixup");
  396. Info.AddValue (memberName, value, value.GetType());
  397. }
  398. public bool IsInstanceReady
  399. {
  400. // Returns true if this object is ready to be assigned to a parent object.
  401. get
  402. {
  403. if (!IsRegistered) return false;
  404. if (IsUnsolvedObjectReference) return false;
  405. // Embedded value objects cannot be assigned to their containers until fully completed
  406. if (ObjectInstance.GetType ().IsValueType && (HasPendingFixups || Info != null))
  407. return false;
  408. return true;
  409. }
  410. }
  411. public bool IsUnsolvedObjectReference
  412. {
  413. get {
  414. return Status != ObjectRecordStatus.ReferenceSolved;
  415. }
  416. }
  417. public bool IsRegistered
  418. {
  419. get {
  420. return Status != ObjectRecordStatus.Unregistered;
  421. }
  422. }
  423. public bool DoFixups (bool asContainer, ObjectManager manager, bool strict)
  424. {
  425. BaseFixupRecord prevFixup = null;
  426. BaseFixupRecord fixup = asContainer ? FixupChainAsContainer : FixupChainAsRequired;
  427. bool allFixed = true;
  428. while (fixup != null)
  429. {
  430. if (fixup.DoFixup (manager, strict))
  431. {
  432. UnchainFixup (fixup, prevFixup, asContainer);
  433. if (asContainer) fixup.ObjectRequired.RemoveFixup (fixup, false);
  434. else fixup.ObjectToBeFixed.RemoveFixup (fixup, true);
  435. }
  436. else
  437. {
  438. prevFixup = fixup;
  439. allFixed = false;
  440. }
  441. fixup = asContainer ? fixup.NextSameContainer : fixup.NextSameRequired;
  442. }
  443. return allFixed;
  444. }
  445. public void RemoveFixup (BaseFixupRecord fixupToRemove, bool asContainer)
  446. {
  447. BaseFixupRecord prevFixup = null;
  448. BaseFixupRecord fixup = asContainer ? FixupChainAsContainer : FixupChainAsRequired;
  449. while (fixup != null)
  450. {
  451. if (fixup == fixupToRemove)
  452. {
  453. UnchainFixup (fixup, prevFixup, asContainer);
  454. return;
  455. }
  456. prevFixup = fixup;
  457. fixup = asContainer ? fixup.NextSameContainer : fixup.NextSameRequired;
  458. }
  459. }
  460. private void UnchainFixup (BaseFixupRecord fixup, BaseFixupRecord prevFixup, bool asContainer)
  461. {
  462. if (prevFixup == null) {
  463. if (asContainer) FixupChainAsContainer = fixup.NextSameContainer;
  464. else FixupChainAsRequired = fixup.NextSameRequired;
  465. }
  466. else {
  467. if (asContainer) prevFixup.NextSameContainer = fixup.NextSameContainer;
  468. else prevFixup.NextSameRequired = fixup.NextSameRequired;
  469. }
  470. }
  471. public void ChainFixup (BaseFixupRecord fixup, bool asContainer)
  472. {
  473. if (asContainer)
  474. {
  475. fixup.NextSameContainer = FixupChainAsContainer;
  476. FixupChainAsContainer = fixup;
  477. }
  478. else
  479. {
  480. fixup.NextSameRequired = FixupChainAsRequired;
  481. FixupChainAsRequired = fixup;
  482. }
  483. }
  484. public bool LoadData (ObjectManager manager, ISurrogateSelector selector, StreamingContext context)
  485. {
  486. if (Info != null)
  487. {
  488. if (Surrogate != null) {
  489. object new_obj = Surrogate.SetObjectData (ObjectInstance, Info, context, SurrogateSelector);
  490. if (new_obj != null)
  491. ObjectInstance = new_obj;
  492. Status = ObjectRecordStatus.ReferenceSolved;
  493. } else if (ObjectInstance is ISerializable) {
  494. object[] pars = new object[] {Info, context};
  495. ConstructorInfo con = ObjectInstance.GetType().GetConstructor (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof (SerializationInfo), typeof (StreamingContext) }, null );
  496. if (con == null) throw new SerializationException ("The constructor to deserialize an object of type " + ObjectInstance.GetType().FullName + " was not found.");
  497. con.Invoke (ObjectInstance, pars);
  498. } else {
  499. throw new SerializationException ("No surrogate selector was found for type " + ObjectInstance.GetType().FullName);
  500. }
  501. Info = null;
  502. }
  503. if (ObjectInstance is IObjectReference && Status != ObjectRecordStatus.ReferenceSolved)
  504. {
  505. try {
  506. ObjectInstance = ((IObjectReference)ObjectInstance).GetRealObject(context);
  507. int n = 100;
  508. while (ObjectInstance is IObjectReference && n > 0) {
  509. object ob = ((IObjectReference)ObjectInstance).GetRealObject (context);
  510. if (ob == ObjectInstance)
  511. break;
  512. ObjectInstance = ob;
  513. n--;
  514. }
  515. if (n == 0)
  516. throw new SerializationException ("The implementation of the IObjectReference interface returns too many nested references to other objects that implement IObjectReference.");
  517. Status = ObjectRecordStatus.ReferenceSolved;
  518. }
  519. catch (NullReferenceException) {
  520. // Give a second chance
  521. return false;
  522. }
  523. }
  524. if (Member != null)
  525. {
  526. // If this object is a value object embedded in another object, the parent
  527. // object must be updated
  528. ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
  529. containerRecord.SetMemberValue (manager, Member, ObjectInstance);
  530. }
  531. else if (ArrayIndex != null)
  532. {
  533. ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
  534. containerRecord.SetArrayValue (manager, ObjectInstance, ArrayIndex);
  535. }
  536. return true;
  537. }
  538. public bool HasPendingFixups
  539. {
  540. get { return FixupChainAsContainer != null; }
  541. }
  542. }
  543. }