Exception.SerializeObjectState 事件

定義

當例外狀況序列化,以建立包含例外狀況相關序列化資料的例外狀況狀態物件時,就會發生此事件。Occurs when an exception is serialized to create an exception state object that contains serialized data about the exception.

protected:
 event EventHandler<System::Runtime::Serialization::SafeSerializationEventArgs ^> ^ SerializeObjectState;
protected event EventHandler<System.Runtime.Serialization.SafeSerializationEventArgs> SerializeObjectState;
member this.SerializeObjectState : EventHandler<System.Runtime.Serialization.SafeSerializationEventArgs> 
Protected Custom Event SerializeObjectState As EventHandler(Of SafeSerializationEventArgs) 

範例

下列範例會定義處理 SerializeObjectState 事件的 BadDivisionExceptionThe following example defines a BadDivisionException that handles the SerializeObjectState event. 它也包含狀態物件,這是一個名為 BadDivisionExceptionState 的嵌套結構,可執行 ISafeSerializationData 介面。It also contains a state object, which is a nested structure named BadDivisionExceptionState that implements the ISafeSerializationData interface.

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Example
{
   public static void Main()
   {
      bool serialized = false;
      var formatter = new BinaryFormatter();
      Double[] values = { 3, 2, 1 };
      Double divisor = 0;
      foreach (var value in values) {
         try {
            BadDivisionException ex = null;
            if (divisor == 0) { 
               if (! serialized) {
                  // Instantiate the exception object.
                  ex = new BadDivisionException(0);
                  // Serialize the exception object.
                  var fs = new FileStream("BadDivision1.dat", 
                                           FileMode.Create);
                  formatter.Serialize(fs, ex);
                  fs.Close();
                  Console.WriteLine("Serialized the exception...");
               }
               else {
                  // Deserialize the exception.
                  var fs = new FileStream("BadDivision1.dat",
                                           FileMode.Open);
                  ex = (BadDivisionException) formatter.Deserialize(fs);
                  // Reserialize the exception.
                  fs.Position = 0;
                  formatter.Serialize(fs, ex);
                  fs.Close();
                  Console.WriteLine("Reserialized the exception...");                                            
               }   
              throw ex; 
            } 
            Console.WriteLine("{0} / {1} = {1}", value, divisor, value/divisor);
         }   
         catch (BadDivisionException e) {
            Console.WriteLine("Bad divisor from a {0} exception: {1}",
                              serialized ? "deserialized" : "new", e.Divisor);             
            serialized = true;
         }   
      }
   }
}

[Serializable] public class BadDivisionException : Exception
{
   // Maintain an internal BadDivisionException state object.
   [NonSerialized] private BadDivisionExceptionState state = new BadDivisionExceptionState();

   public BadDivisionException(Double divisor)
   {
      state.Divisor = divisor;
      HandleSerialization();      
   }
   
   private void HandleSerialization()
   {
      SerializeObjectState += delegate(object exception, SafeSerializationEventArgs eventArgs) 
                                      { 
                                          eventArgs.AddSerializedState(state);
                                      };
   }
   
   public Double Divisor
   { get { return state.Divisor; } }

   [Serializable] private struct BadDivisionExceptionState : ISafeSerializationData 
   {
      private Double badDivisor;
      
      public Double Divisor
      { get { return badDivisor; } 
        set { badDivisor = value; } }

      void ISafeSerializationData.CompleteDeserialization(object deserialized)
      { 
         var ex = deserialized as BadDivisionException;
         ex.HandleSerialization();
         ex.state = this; 
      }
   }
}
// The example displays the following output:
//       Serialized the exception...
//       Bad divisor from a new exception: 0
//       Reserialized the exception...
//       Bad divisor from a deserialized exception: 0
//       Reserialized the exception...
//       Bad divisor from a deserialized exception: 0
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
           
Module Example
   Public Sub Main()
      Dim serialized As Boolean = False
      Dim formatter As New BinaryFormatter()
      Dim values() As Double = { 3, 2, 1 }
      Dim divisor As Double = 0
      For Each value In values
         Try
            Dim ex As BadDivisionException = Nothing
            If divisor = 0 Then 
               If Not serialized Then
                  ' Instantiate the exception object.
                  ex = New BadDivisionException(0)
                  ' Serialize the exception object.
                  Dim fs As New FileStream("BadDivision1.dat", 
                                           FileMode.Create)
                  formatter.Serialize(fs, ex)
                  fs.Close()
                  Console.WriteLine("Serialized the exception...")
               Else
                  ' Deserialize the exception.
                  Dim fs As New FileStream("BadDivision1.dat",
                                           FileMode.Open)
                  ex = CType(formatter.Deserialize(fs), BadDivisionException)
                  ' Reserialize the exception.
                  fs.Position = 0
                  formatter.Serialize(fs, ex)
                  fs.Close()
                  Console.WriteLine("Reserialized the exception...")                                            
               End If   
              Throw ex 
            End If 
            Console.WriteLine("{0} / {1} = {1}", value, divisor, value/divisor)
         Catch e As BadDivisionException
            Console.WriteLine("Bad divisor from a {0} exception: {1}",
                              If(serialized, "deserialized", "new"), e.Divisor)             
            serialized = True
         End Try   
      Next
   End Sub
End Module

<Serializable> Public Class BadDivisionException : Inherits Exception
   ' Maintain an internal BadDivisionException state object.
   <NonSerialized> Private state As New BadDivisionExceptionState()

   Public Sub New(divisor As Double)
      state.Divisor = divisor
      HandleSerialization()      
   End Sub
   
   Private Sub HandleSerialization()
      AddHandler SerializeObjectState, 
                 Sub(exception As Object, eventArgs As SafeSerializationEventArgs)
                    eventArgs.AddSerializedState(state)
                 End Sub
   End Sub
   
   Public ReadOnly Property Divisor As Double
      Get
         Return state.Divisor
      End Get      
   End Property

   <Serializable> Private Structure BadDivisionExceptionState 
                                    Implements ISafeSerializationData
      private badDivisor As Double
      
      Public Property Divisor As Double
         Get
            Return badDivisor
         End Get
         Set
            badDivisor = value
         End Set
      End Property 

      Sub CompleteDeserialization(deserialized As Object) _
            Implements ISafeSerializationData.CompleteDeserialization
         Dim ex As BadDivisionException = TryCast(deserialized, BadDivisionException)
         ex.HandleSerialization()
         ex.state = Me 
      End Sub
   End Structure
End Class
' The example displays the following output:
'       Serialized the exception...
'       Bad divisor from a new exception: 0
'       Reserialized the exception...
'       Bad divisor from a deserialized exception: 0
'       Reserialized the exception...
'       Bad divisor from a deserialized exception: 0

當發生浮點零除的情況時,就會擲回 BadDivisionException 例外狀況。The BadDivisionException exception is thrown when a floating-point division by zero occurs. 在第一個除數為零的情況下,此範例會具現化 BadDivisionException 物件、將它序列化,並擲回例外狀況。During the first division by zero, the example instantiates a BadDivisionException object, serializes it, and throws the exception. 當後續的除法零發生時,範例會將先前序列化的物件還原序列化,並加以重新序列化,然後擲回例外狀況。When subsequent divisions by zero occur, the example deserializes the previously serialized object, reserializes it, and throws the exception. 為了提供物件序列化、還原序列化、reserialization 和還原序列化,此範例會將 SerializeObjectState 事件處理常式加入 BadDivisionException 類別的函式和 ISafeSerializationData.CompleteDeserialization 的執行中。To provide for object serialization, deserialization, reserialization, and deserialization, the example adds the SerializeObjectState event handler both in the BadDivisionException class constructor and in the ISafeSerializationData.CompleteDeserialization implementation.

備註

例外狀況狀態物件會執行 ISafeSerializationData 介面。The exception state object implements the ISafeSerializationData interface.

SerializeObjectState 事件訂閱時,例外狀況會還原序列化並建立為空的例外狀況。When the SerializeObjectState event is subscribed to, the exception is deserialized and created as an empty exception. 例外狀況的函式不會執行,而且例外狀態也會還原序列化。The exception's constructor is not run, and the exception state is also deserialized. 接著會通知例外狀況狀態物件的 CompleteDeserialization 回呼方法,使其可以將已還原序列化的資料推送至空的例外狀況。The CompleteDeserialization callback method of the exception state object is then notified so that it can push deserialized data into the empty exception.

SerializeObjectState 事件可讓透明的例外狀況類型序列化和還原序列化例外狀況資料。The SerializeObjectState event enables transparent exception types to serialize and deserialize exception data. 透明程式碼可以在其操作的許可權集合範圍內執行命令,但無法執行、呼叫、衍生自或包含關鍵程式碼。Transparent code can execute commands within the bounds of the permission set it is operating within, but cannot execute, call, derive from, or contain critical code.

如果 SerializeObjectState 事件沒有訂閱,則會使用 Exception 的「函式」,以平常的方式進行還原序列化。If the SerializeObjectState event is not subscribed to, deserialization occurs as usual using the Exception constructor.

一般來說,會在例外狀況的函式中加入 SerializeObjectState 事件的處理常式,以提供其序列化。Typically, a handler for the SerializeObjectState event is added in the exception's constructor to provide for its serialization. 但是,由於當 SerializeObjectState 事件處理常式執行時,不會執行此函式,因此當您嘗試還原序列化例外狀況時,序列化已還原序列化的例外狀況可能會擲回 SerializationException 例外狀況。But because the constructor is not executed when the SerializeObjectState event handler executes, serializing a deserialized exception can throw a SerializationException exception when you try to deserialize the exception. 若要避免這種情況,您也應該在 ISafeSerializationData.CompleteDeserialization 方法中加入 SerializeObjectState 事件的處理常式。To avoid this, you should also add the handler for the SerializeObjectState event in the ISafeSerializationData.CompleteDeserialization method. 如需圖例,請參閱範例一節。See the Examples section for an illustration.

給繼承者的注意事項

如果此事件訂閱並使用,則在繼承階層架構中的所有衍生類型都必須執行相同的序列化機制。If this event is subscribed to and used, all derived types that follow in the inheritance hierarchy must implement the same serialization mechanism.

適用於