ObjectManager.cs :  » 2.6.4-mono-.net-core » System.Runtime » System » Runtime » Serialization » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Runtime 
System.Runtime » System » Runtime » Serialization » ObjectManager.cs
//
// System.Runtime.Serialization.ObjectManager.cs
//
// Author: Lluis Sanchez Gual (lluis@ideary.com)
//
// (C) 2003 Lluis Sanchez Gual
//

//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections;
using System.Reflection;

namespace System.Runtime.Serialization{
  [System.Runtime.InteropServices.ComVisibleAttribute (true)]
  public class ObjectManager
  {
    // All objects are chained in the same order as they have been registered
    ObjectRecord _objectRecordChain = null;
    ObjectRecord _lastObjectRecord = null;

    ArrayList _deserializedRecords = new ArrayList();
    ArrayList _onDeserializedCallbackRecords = new ArrayList();
    Hashtable _objectRecords = new Hashtable();
    bool _finalFixup = false;

    ISurrogateSelector _selector;
    StreamingContext _context;
    int _registeredObjectsCount = 0;

    public ObjectManager(ISurrogateSelector selector, StreamingContext context)
    {
      _selector = selector;
      _context = context;
    }

    public virtual void DoFixups()
    {
      _finalFixup = true;

      try
      {
        if (_registeredObjectsCount < _objectRecords.Count)
          throw new SerializationException ("There are some fixups that refer to objects that have not been registered");


        ObjectRecord last = _lastObjectRecord;
        bool firstCicle = true;

        // Solve al pending fixups of all objects

        ObjectRecord record = _objectRecordChain;
        while (record != null)
        {
          bool ready = !(record.IsUnsolvedObjectReference && firstCicle);
          if (ready) ready = record.DoFixups (true, this, true);
          if (ready) ready = record.LoadData(this, _selector, _context);

          ObjectRecord next;

          if (ready)
          {
            if (record.OriginalObject is IDeserializationCallback)
              _deserializedRecords.Add (record);

            SerializationCallbacks sc = SerializationCallbacks
              .GetSerializationCallbacks (record.OriginalObject.GetType ());
            if (sc.HasDeserializedCallbacks)
              _onDeserializedCallbackRecords.Add (record);
            next = record.Next;
          }
          else
          {
            // There must be an unresolved IObjectReference instance.
            // Chain the record at the end so it is solved later

            if ((record.ObjectInstance is IObjectReference) && !firstCicle)
            {
              if (record.Status == ObjectRecordStatus.ReferenceSolvingDelayed)
                throw new SerializationException ("The object with ID " + record.ObjectID + " could not be resolved");
              else
                record.Status = ObjectRecordStatus.ReferenceSolvingDelayed;
            }

            if (record != _lastObjectRecord) {
              next = record.Next;
              record.Next = null;
              _lastObjectRecord.Next = record;
              _lastObjectRecord = record;
            }
            else
              next = record;
          }

          if (record == last) firstCicle = false;
          record = next;
        }
      }
      finally
      {
        _finalFixup = false;
      }
    }

    internal ObjectRecord GetObjectRecord (long objectID)
    {
      ObjectRecord rec = (ObjectRecord)_objectRecords[objectID];
      if (rec == null)
      {
        if (_finalFixup) throw new SerializationException ("The object with Id " + objectID + " has not been registered");
        rec = new ObjectRecord();
        rec.ObjectID = objectID;
        _objectRecords[objectID] = rec;
      }
      if (!rec.IsRegistered && _finalFixup) throw new SerializationException ("The object with Id " + objectID + " has not been registered");
      return rec;
    }

    public virtual object GetObject (long objectID)
    {
      if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
      ObjectRecord rec = (ObjectRecord)_objectRecords[objectID];
      if (rec == null || !rec.IsRegistered) return null;
      else return rec.ObjectInstance;
    }

    public virtual void RaiseDeserializationEvent ()
    {
      for (int i = _onDeserializedCallbackRecords.Count-1; i >= 0; i--)
      {
        ObjectRecord record = (ObjectRecord) _onDeserializedCallbackRecords [i];
        RaiseOnDeserializedEvent (record.OriginalObject);
      }
      for (int i = _deserializedRecords.Count-1; i >= 0; i--)
      {
        ObjectRecord record = (ObjectRecord) _deserializedRecords [i];
        IDeserializationCallback obj = record.OriginalObject as IDeserializationCallback;
        if (obj != null) obj.OnDeserialization (this);
      }

    }

    public void RaiseOnDeserializingEvent (object obj)
    {
      SerializationCallbacks sc = SerializationCallbacks
        .GetSerializationCallbacks (obj.GetType ());
      sc.RaiseOnDeserializing (obj, _context);
    }

    void RaiseOnDeserializedEvent (object obj)
    {
      SerializationCallbacks sc = SerializationCallbacks
        .GetSerializationCallbacks (obj.GetType ());
      sc.RaiseOnDeserialized (obj, _context);
    }

    private void AddFixup (BaseFixupRecord record)
    {
      record.ObjectToBeFixed.ChainFixup (record, true);
      record.ObjectRequired.ChainFixup (record, false);
    }

    public virtual void RecordArrayElementFixup (long arrayToBeFixed, int index, long objectRequired)
    {
      if (arrayToBeFixed <= 0) throw new ArgumentOutOfRangeException("arrayToBeFixed","The arrayToBeFixed parameter is less than or equal to zero");
      if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
      ArrayFixupRecord record = new ArrayFixupRecord(GetObjectRecord(arrayToBeFixed), index, GetObjectRecord(objectRequired));
      AddFixup (record);
    }

    public virtual void RecordArrayElementFixup (long arrayToBeFixed, int[] indices, long objectRequired)
    {
      if (arrayToBeFixed <= 0) throw new ArgumentOutOfRangeException("arrayToBeFixed","The arrayToBeFixed parameter is less than or equal to zero");
      if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
      if (indices == null) throw new ArgumentNullException("indices");
      MultiArrayFixupRecord record = new MultiArrayFixupRecord (GetObjectRecord(arrayToBeFixed), indices, GetObjectRecord(objectRequired));
      AddFixup (record);
    }

    public virtual void RecordDelayedFixup (long objectToBeFixed, string memberName, long objectRequired)
    {
      if (objectToBeFixed <= 0) throw new ArgumentOutOfRangeException("objectToBeFixed","The objectToBeFixed parameter is less than or equal to zero");
      if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
      if (memberName == null) throw new ArgumentNullException("memberName");
      DelayedFixupRecord record = new DelayedFixupRecord (GetObjectRecord(objectToBeFixed), memberName, GetObjectRecord(objectRequired));
      AddFixup (record);
    }

    public virtual void RecordFixup (long objectToBeFixed, MemberInfo member, long objectRequired)
    {
      if (objectToBeFixed <= 0) throw new ArgumentOutOfRangeException("objectToBeFixed","The objectToBeFixed parameter is less than or equal to zero");
      if (objectRequired <= 0) throw new ArgumentOutOfRangeException("objectRequired","The objectRequired parameter is less than or equal to zero");
      if (member == null) throw new ArgumentNullException("member");
      FixupRecord record = new FixupRecord (GetObjectRecord(objectToBeFixed), member, GetObjectRecord(objectRequired));
      AddFixup (record);
    }

    private void RegisterObjectInternal (object obj, ObjectRecord record)
    {
      if (obj == null) throw new ArgumentNullException("obj");

      if (record.IsRegistered)
      {
        if (record.OriginalObject != obj) throw new SerializationException ("An object with Id " + record.ObjectID + " has already been registered");
        else return;
      }

      record.ObjectInstance = obj;
      record.OriginalObject = obj;

      if (obj is IObjectReference) record.Status = ObjectRecordStatus.ReferenceUnsolved;
      else record.Status = ObjectRecordStatus.ReferenceSolved;

      if (_selector != null) {
        record.Surrogate = _selector.GetSurrogate (
          obj.GetType(), _context, out record.SurrogateSelector);
        if (record.Surrogate != null)
          record.Status = ObjectRecordStatus.ReferenceUnsolved;
      }

      record.DoFixups (true, this, false);
      record.DoFixups (false, this, false);
      _registeredObjectsCount++;

      // Adds the object to the chain of registered objects. This chain
      // is needed to be able to to perform the final fixups in the right order

      if (_objectRecordChain == null)
      {
        _objectRecordChain = record;
        _lastObjectRecord = record;
      }
      else 
      {
        _lastObjectRecord.Next = record;
        _lastObjectRecord = record;
      }
    }


    public virtual void RegisterObject (object obj, long objectID)
    {
      if (obj == null) throw new ArgumentNullException("obj", "The obj parameter is null.");
      if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
      RegisterObjectInternal (obj, GetObjectRecord (objectID));
    }

    public void RegisterObject (object obj, long objectID, SerializationInfo info)
    {
      if (obj == null) throw new ArgumentNullException("obj", "The obj parameter is null.");
      if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");
      
      ObjectRecord record = GetObjectRecord (objectID);
      record.Info = info;
      RegisterObjectInternal (obj, record);
    }

    public void RegisterObject (object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member)
    {
      RegisterObject (obj, objectID, info, idOfContainingObj, member, null);
    }

    public void RegisterObject( object obj, long objectID, SerializationInfo info, long idOfContainingObj, MemberInfo member, int[] arrayIndex)
    {
      if (obj == null) throw new ArgumentNullException("obj", "The obj parameter is null.");
      if (objectID <= 0) throw new ArgumentOutOfRangeException("objectID","The objectID parameter is less than or equal to zero");

      ObjectRecord record = GetObjectRecord (objectID);
      record.Info = info;
      record.IdOfContainingObj = idOfContainingObj;
      record.Member = member;
      record.ArrayIndex = arrayIndex;
      RegisterObjectInternal (obj, record);
    }
  }



  // Fixup types. There is a fixup class for each fixup type.

  // BaseFixupRecord
  // Base class for all fixups

  internal abstract class BaseFixupRecord
  {
    public BaseFixupRecord(ObjectRecord objectToBeFixed, ObjectRecord objectRequired)
    {
      ObjectToBeFixed = objectToBeFixed;
      ObjectRequired = objectRequired;
    }

    public bool DoFixup (ObjectManager manager, bool strict)
    {
      if (ObjectToBeFixed.IsRegistered && ObjectRequired.IsInstanceReady)
      {
        FixupImpl (manager);
        return true;
      }
      else if (strict)
      {
        if (!ObjectToBeFixed.IsRegistered) throw new SerializationException ("An object with ID " + ObjectToBeFixed.ObjectID + " was included in a fixup, but it has not been registered");
        else if (!ObjectRequired.IsRegistered) throw new SerializationException ("An object with ID " + ObjectRequired.ObjectID + " was included in a fixup, but it has not been registered");
        else return false;
      }
      else
        return false;
    }

    protected abstract void FixupImpl (ObjectManager manager);

    internal protected ObjectRecord ObjectToBeFixed;
    internal protected ObjectRecord ObjectRequired;

    public BaseFixupRecord NextSameContainer;
    public BaseFixupRecord NextSameRequired;
  }

  // ArrayFixupRecord
  // Fixup for assigning a value to one position of an array

  internal class ArrayFixupRecord : BaseFixupRecord
  {
    int _index;

    public ArrayFixupRecord (ObjectRecord objectToBeFixed, int index, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
      _index = index;
    }

    protected override void FixupImpl (ObjectManager manager) {
      Array array = (Array)ObjectToBeFixed.ObjectInstance;
      array.SetValue (ObjectRequired.ObjectInstance, _index);
    }
  }

  // MultiArrayFixupRecord
  // Fixup for assigning a value to several positions of an array

  internal class MultiArrayFixupRecord : BaseFixupRecord
  {
    int[] _indices;

    public MultiArrayFixupRecord (ObjectRecord objectToBeFixed, int[] indices, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
      _indices = indices;
    }

    protected override void FixupImpl (ObjectManager manager) {
      ObjectToBeFixed.SetArrayValue (manager, ObjectRequired.ObjectInstance, _indices);
    }
  }

  // FixupRecord
  // Fixup for assigning a value to a member of an object

  internal class FixupRecord: BaseFixupRecord
  {
    public MemberInfo _member;

    public FixupRecord (ObjectRecord objectToBeFixed, MemberInfo member, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
      _member = member;
    }

    protected override void FixupImpl (ObjectManager manager) {
      ObjectToBeFixed.SetMemberValue (manager, _member, ObjectRequired.ObjectInstance);
    }
  }

  // DelayedFixupRecord
  // Fixup for assigning a value to a SerializationInfo of an object

  internal class DelayedFixupRecord: BaseFixupRecord
  {
    public string _memberName;

    public DelayedFixupRecord (ObjectRecord objectToBeFixed, string memberName, ObjectRecord objectRequired): base (objectToBeFixed, objectRequired) {
      _memberName = memberName;
    }

    protected override void FixupImpl (ObjectManager manager) {
      ObjectToBeFixed.SetMemberValue (manager, _memberName, ObjectRequired.ObjectInstance);
    }
  }

  // Object Record

  internal enum ObjectRecordStatus: byte { Unregistered, ReferenceUnsolved, ReferenceSolvingDelayed, ReferenceSolved }

  internal class ObjectRecord
  {
    public ObjectRecordStatus Status = ObjectRecordStatus.Unregistered;
    public object OriginalObject;
    public object ObjectInstance;
    public long ObjectID;
    public SerializationInfo Info;
    public long IdOfContainingObj;
    public ISerializationSurrogate Surrogate;
    public ISurrogateSelector SurrogateSelector;
    public MemberInfo Member;
    public int[] ArrayIndex;
    public BaseFixupRecord FixupChainAsContainer;
    public BaseFixupRecord FixupChainAsRequired;
    public ObjectRecord Next;

    public void SetMemberValue (ObjectManager manager, MemberInfo member, object value)
    {
      if (member is FieldInfo)
        ((FieldInfo)member).SetValue (ObjectInstance, value);
      else if (member is PropertyInfo)
        ((PropertyInfo)member).SetValue (ObjectInstance, value, null);
      else throw new SerializationException ("Cannot perform fixup");

      if (Member != null)
      {
        ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
        if (containerRecord.IsRegistered)
          containerRecord.SetMemberValue (manager, Member, ObjectInstance);
      }
      else if (ArrayIndex != null)
      {
        ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
        if (containerRecord.IsRegistered)
          containerRecord.SetArrayValue (manager, ObjectInstance, ArrayIndex);
      }
    }
    public void SetArrayValue (ObjectManager manager, object value, int[] indices)
    {
      ((Array)ObjectInstance).SetValue (value, indices);
    }

    public void SetMemberValue (ObjectManager manager, string memberName, object value)
    {
      if (Info == null) throw new SerializationException ("Cannot perform fixup");
      Info.AddValue (memberName, value, value.GetType());
    }

    public bool IsInstanceReady
    {
      // Returns true if this object is ready to be assigned to a parent object.
      get
      {
        if (!IsRegistered) return false;
        if (IsUnsolvedObjectReference) return false;

        // Embedded value objects cannot be assigned to their containers until fully completed
        if (ObjectInstance.GetType ().IsValueType && (HasPendingFixups || Info != null))
          return false;

        return true;
      }
    }

    public bool IsUnsolvedObjectReference
    {
      get  {
        return Status != ObjectRecordStatus.ReferenceSolved;
      }
    }

    public bool IsRegistered
    {
      get {
        return Status != ObjectRecordStatus.Unregistered;
      }
    }

    public bool DoFixups (bool asContainer, ObjectManager manager, bool strict)
    {
      BaseFixupRecord prevFixup = null;
      BaseFixupRecord fixup = asContainer ? FixupChainAsContainer : FixupChainAsRequired;
      bool allFixed = true;

      while (fixup != null)
      {
        if (fixup.DoFixup (manager, strict))
        {
          UnchainFixup (fixup, prevFixup, asContainer);
          if (asContainer) fixup.ObjectRequired.RemoveFixup (fixup, false);
          else fixup.ObjectToBeFixed.RemoveFixup (fixup, true);
        }
        else
        {
          prevFixup = fixup;
          allFixed = false;
        }

        fixup = asContainer ? fixup.NextSameContainer : fixup.NextSameRequired;
      }
      return allFixed;
    }

    public void RemoveFixup (BaseFixupRecord fixupToRemove, bool asContainer)
    {
      BaseFixupRecord prevFixup = null;
      BaseFixupRecord fixup = asContainer ? FixupChainAsContainer : FixupChainAsRequired;
      while (fixup != null)
      {
        if (fixup == fixupToRemove) 
        {
          UnchainFixup (fixup, prevFixup, asContainer);
          return;
        }
        prevFixup = fixup;
        fixup = asContainer ? fixup.NextSameContainer : fixup.NextSameRequired;
      }
    }

    private void UnchainFixup (BaseFixupRecord fixup, BaseFixupRecord prevFixup, bool asContainer)
    {
      if (prevFixup == null) {
        if (asContainer) FixupChainAsContainer = fixup.NextSameContainer;
        else FixupChainAsRequired = fixup.NextSameRequired;
      }
      else {
        if (asContainer) prevFixup.NextSameContainer = fixup.NextSameContainer;
        else prevFixup.NextSameRequired = fixup.NextSameRequired;
      }
    }

    public void ChainFixup (BaseFixupRecord fixup, bool asContainer)
    {
      if (asContainer) 
      {
        fixup.NextSameContainer = FixupChainAsContainer;
        FixupChainAsContainer = fixup;
      }
      else 
      {
        fixup.NextSameRequired = FixupChainAsRequired;
        FixupChainAsRequired = fixup;
      }
    }

    public bool LoadData (ObjectManager manager, ISurrogateSelector selector, StreamingContext context)
    {
      if (Info != null)
      {
        if (Surrogate != null) {
          object new_obj = Surrogate.SetObjectData (ObjectInstance, Info, context, SurrogateSelector);
          if (new_obj != null)
            ObjectInstance = new_obj;
          Status = ObjectRecordStatus.ReferenceSolved;
        } else if (ObjectInstance is ISerializable) {
          object[] pars = new object[] {Info, context};
          ConstructorInfo con = ObjectInstance.GetType().GetConstructor (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof (SerializationInfo), typeof (StreamingContext) }, null );
          if (con == null) throw new SerializationException ("The constructor to deserialize an object of type " + ObjectInstance.GetType().FullName + " was not found.");
          con.Invoke (ObjectInstance, pars);
        } else {
          throw new SerializationException ("No surrogate selector was found for type " + ObjectInstance.GetType().FullName);
        }

        Info = null;
      }

      if (ObjectInstance is IObjectReference && Status != ObjectRecordStatus.ReferenceSolved)
      {
        try {
          ObjectInstance = ((IObjectReference)ObjectInstance).GetRealObject(context);
          int n = 100;
          while (ObjectInstance is IObjectReference && n > 0) {
            object ob = ((IObjectReference)ObjectInstance).GetRealObject (context);
            if (ob == ObjectInstance)
              break;
            ObjectInstance = ob;
            n--;
          }
          if (n == 0)
            throw new SerializationException ("The implementation of the IObjectReference interface returns too many nested references to other objects that implement IObjectReference.");
          
          Status = ObjectRecordStatus.ReferenceSolved;
        }
        catch (NullReferenceException) {
          // Give a second chance
          return false;
        }
      }

      if (Member != null)
      {
        // If this object is a value object embedded in another object, the parent
        // object must be updated

        ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
        containerRecord.SetMemberValue (manager, Member, ObjectInstance);
      }
      else if (ArrayIndex != null)
      {
        ObjectRecord containerRecord = manager.GetObjectRecord (IdOfContainingObj);
        containerRecord.SetArrayValue (manager, ObjectInstance, ArrayIndex);
      }

      return true;
    }

    public bool HasPendingFixups
    {
      get { return FixupChainAsContainer != null; }
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.