ObjectManager 类

在对象进行反序列化时对其进行跟踪。

**命名空间:**System.Runtime.Serialization
**程序集:**mscorlib(在 mscorlib.dll 中)

语法

声明
<ComVisibleAttribute(True)> _
Public Class ObjectManager
用法
Dim instance As ObjectManager
[ComVisibleAttribute(true)] 
public class ObjectManager
[ComVisibleAttribute(true)] 
public ref class ObjectManager
/** @attribute ComVisibleAttribute(true) */ 
public class ObjectManager
ComVisibleAttribute(true) 
public class ObjectManager

备注

在反序列化过程中,Formatter 会查询 ObjectManager,以确定对序列化流中对象的引用是否引用已经反序列化的对象(后向引用)或引用尚未反序列化的对象(前向引用)。如果序列化流中的引用是前向引用,Formatter 则可以向 ObjectManager 注册修正。如果序列化流中的引用是后向引用,Formatter 将立即完成该引用。修正是指完成在对象反序列化进程中尚未完成的对象引用的过程。当所需对象都已反序列化后,ObjectManager 将完成引用。

ObjectManager 遵循一组规则,这些规则指定修正的顺序。所有实现 ISerializable 或具有 ISerializationSurrogate 的对象都可以要求它们通过 SerializationInfo 传输的所有对象在对象树反序列化时变为可用。但是,父对象不能假定在其被完全反序列化时其所有子对象将被完全完成。所有子对象都将出现,但孙对象并不一定都会出现。如果对象需要执行某些操作,而这些操作依赖于在其子对象上执行代码,它可以延迟这些操作,实现 IDeserializationCallback 接口,然后仅在此接口上回调该对象时执行代码。

示例

下面的代码示例演示如何使用 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

继承层次结构

System.Object
  System.Runtime.Serialization.ObjectManager

线程安全

此类型的任何公共静态(Visual Basic 中的 Shared)成员都是线程安全的,但不保证所有实例成员都是线程安全的。

平台

Windows 98、Windows 2000 SP4、Windows Millennium Edition、Windows Server 2003、Windows XP Media Center Edition、Windows XP Professional x64 Edition、Windows XP SP2、Windows XP Starter Edition

.NET Framework 并不是对每个平台的所有版本都提供支持。有关受支持版本的列表,请参见系统要求

版本信息

.NET Framework

受以下版本支持:2.0、1.1、1.0

请参见

参考

ObjectManager 成员
System.Runtime.Serialization 命名空间