ObjectManager 類別

定義

追蹤物件在去序列化過程中的狀態。

public ref class ObjectManager
public class ObjectManager
[System.Runtime.InteropServices.ComVisible(true)]
public class ObjectManager
type ObjectManager = class
[<System.Runtime.InteropServices.ComVisible(true)>]
type ObjectManager = class
Public Class ObjectManager
繼承
ObjectManager
屬性

範例

以下程式碼範例展示了如何利用該 ObjectManager 類別在物件圖中走遍,每個物件只遍歷一次。

using System;
using System.Text;
using System.Collections;
using System.Runtime.Serialization;
using System.Reflection;

// This class walks through all the objects once in an object graph.
public sealed class ObjectWalker : IEnumerable, IEnumerator {
   private Object m_current;

   // This stack contains the set of objects that will be enumerated.
   private Stack m_toWalk = new Stack();

   // The ObjectIDGenerator ensures that each object is enumerated just once.
   private ObjectIDGenerator m_idGen = new ObjectIDGenerator();

   // Construct an ObjectWalker passing the root of the object graph.
   public ObjectWalker(Object root) {
      Schedule(root);
   }

   // Return an enumerator so this class can be used with foreach.
   public IEnumerator GetEnumerator() {
      return this;
   }

   // Resetting the enumerator is not supported.
   public void Reset() {
      throw new NotSupportedException("Resetting the enumerator is not supported.");
   }

   // Return the enumeration's current object.
   public Object Current { get { return m_current; } }

   // Walk the reference of the passed-in object.
   private void Schedule(Object toSchedule) {
      if (toSchedule == null) return;

      // Ask the ObjectIDManager if this object has been examined before.
      Boolean firstOccurrence;
      m_idGen.GetId(toSchedule, out firstOccurrence);

      // If this object has been examined before, do not look at it again just return.
      if (!firstOccurrence) return;

      if (toSchedule.GetType().IsArray) {
         // The object is an array, schedule each element of the array to be looked at.
         foreach (Object item in ((Array)toSchedule)) Schedule(item);
      } else {
         // The object is not an array, schedule this object to be looked at.
         m_toWalk.Push(toSchedule);
      }
   }

   // Advance to the next item in the enumeration.
   public Boolean MoveNext() {
      // If there are no more items to enumerate, return false.
      if (m_toWalk.Count == 0) return false;

      // Check if the object is a terminal object (has no fields that refer to other objects).
      if (!IsTerminalObject(m_current = m_toWalk.Pop())) {
         // The object does have field, schedule the object's instance fields to be enumerated.
         foreach (FieldInfo fi in m_current.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
            Schedule(fi.GetValue(m_current));
         }
      }
      return true;
   }

   // Returns true if the object has no data fields with information of interest.
   private Boolean IsTerminalObject(Object data) {
      Type t = data.GetType();
      return t.IsPrimitive || t.IsEnum || t.IsPointer || data is String;
   }
}

public sealed class App {
   // Define some fields in the class to test the ObjectWalker.
   public String name = "Fred";
   public Int32 Age = 40;

   static void Main() {
      // Build an object graph using an array that refers to various objects.
      Object[] data = new Object[] { "Jeff", 123, 555L, (Byte) 35, new App() };

      // Construct an ObjectWalker and pass it the root of the object graph.
      ObjectWalker ow = new ObjectWalker(data);

      // Enumerate all of the objects in the graph and count the number of objects.
      Int64 num = 0;
      foreach (Object o in ow) {
         // Display each object's type and value as a string.
         Console.WriteLine("Object #{0}: Type={1}, Value's string={2}",
            num++, o.GetType(), o.ToString());
      }
   }
}

// This code produces the following output.
//
// Object #0: Type=App, Value's string=App
// Object #1: Type=System.Int32, Value's string=40
// Object #2: Type=System.String, Value's string=Fred
// Object #3: Type=System.Byte, Value's string=35
// Object #4: Type=System.Int64, Value's string=555
// Object #5: Type=System.Int32, Value's string=123
// Object #6: Type=System.String, Value's string=Jeff

備註

在反序列化過程中,查詢 FormatterObjectManager 為了判斷序列化串流中對物件的引用是指已反序列化的物件(向後參考),還是尚未被反序列化的物件(前向參考)。 如果序列化串流中的參考是前向參考,則Formatter可以註冊一個固定。ObjectManager 如果序列化串流中的參考是向後參考,則會 Formatter 立即完成該參考。 修正是指在物件反序列化過程中尚未完成的物件參考最終完成的過程。 當所需的物件被反序列化後,將 ObjectManager 完成引用。

ObjectManager 遵循一套規則來決定固定順序。 所有實作 ISerializable 或擁有 的 ISerializationSurrogate 物件,當物件樹被反序列化時,都可以預期它們所透過 SerializationInfo 的所有物件都能被使用。 然而,父物件不能假設所有子物件在完全反序列化後都會完全完成。 所有子物件都會存在,但不一定所有子物件都會存在。 如果物件需要執行依賴於子物件執行程式碼的某些動作,它可以延遲這些動作、實作介面 IDeserializationCallback ,並只在被呼叫回來時執行程式碼。

建構函式

名稱 Description
ObjectManager(ISurrogateSelector, StreamingContext)

初始化 ObjectManager 類別的新執行個體。

方法

名稱 Description
DoFixups()

負責所有錄製的修正。

Equals(Object)

判斷指定的 物件是否等於目前的物件。

(繼承來源 Object)
GetHashCode()

做為預設雜湊函式。

(繼承來源 Object)
GetObject(Int64)

回傳指定物件 ID 的物件。

GetType()

取得目前實例的 Type

(繼承來源 Object)
MemberwiseClone()

建立目前 Object的淺層複本。

(繼承來源 Object)
RaiseDeserializationEvent()

將反序列化事件提升至任何實 IDeserializationCallback作 的註冊物件。

RaiseOnDeserializingEvent(Object)

呼叫標記為 OnDeserializingAttribute的方法。

RecordArrayElementFixup(Int64, Int32, Int64)

記錄陣列中一個元素的修正。

RecordArrayElementFixup(Int64, Int32[], Int64)

記錄陣列中指定元素的修正,供日後執行。

RecordDelayedFixup(Int64, String, Int64)

記錄物件成員的修正,之後執行。

RecordFixup(Int64, MemberInfo, Int64)

記錄物件成員的修正,供日後執行。

RegisterObject(Object, Int64, SerializationInfo, Int64, MemberInfo, Int32[])

在物件反序列化時,註冊包含在陣列中的成員,並將其與 objectID關聯,並記錄 SerializationInfo

RegisterObject(Object, Int64, SerializationInfo, Int64, MemberInfo)

在物件被反序列化時註冊其成員,並將其與 objectID關聯,並記錄 SerializationInfo

RegisterObject(Object, Int64, SerializationInfo)

在物件被去序列化時註冊,並將其與 objectID關聯,並記錄 SerializationInfo 與其使用的物件。

RegisterObject(Object, Int64)

在物件被反序列化時註冊,並將其與 objectID關聯。

ToString()

傳回表示目前 物件的字串。

(繼承來源 Object)

適用於