Dies ist ein alter Thread, der jedoch eine andere Antwort verdient.
@mson fragte sich, warum jemand eine Ausnahme serialisieren möchte. Hier ist unser Grund dafür:
Wir haben eine Prism / MVVM-Anwendung mit Ansichten in Silverlight und WPF mit dem Datenmodell in WCF-Diensten. Wir möchten sicherstellen, dass Datenzugriff und Aktualisierungen fehlerfrei erfolgen. Wenn ein Fehler auftritt, möchten wir ihn sofort informieren und den Benutzer darüber informieren, dass möglicherweise ein Fehler aufgetreten ist. Unsere Anwendungen öffnen ein Fenster, das den Benutzer über einen möglichen Fehler informiert. Die eigentliche Ausnahme wird dann per E-Mail an uns gesendet und zur Verfolgung in SpiceWorks gespeichert. Wenn der Fehler bei einem WCF-Dienst auftritt, möchten wir die vollständige Ausnahme an den Client zurückgeben, damit dieser Prozess stattfinden kann.
Hier ist die von mir entwickelte Lösung, die sowohl von WPF- als auch von Silverlight-Clients verarbeitet werden kann. Die folgenden Methoden befinden sich in einer "allgemeinen" Klassenbibliothek von Methoden, die von mehreren Anwendungen in jeder Schicht verwendet werden.
Ein Byte-Array kann einfach von einem WCF-Dienst serialisiert werden. So ziemlich jedes Objekt kann in ein Byte-Array konvertiert werden.
Ich habe mit zwei einfachen Methoden begonnen, Object2Bytes und Bytes2Object. Diese konvertieren jedes Objekt in ein Byte-Array und zurück. NetDataContractSerializer stammt aus der Windows-Version des System.Runtime.Serialization-Namespace.
Public Function Object2Bytes(ByVal value As Object) As Byte()
Dim bytes As Byte()
Using ms As New MemoryStream
Dim ndcs As New NetDataContractSerializer()
ndcs.Serialize(ms, value)
bytes = ms.ToArray
End Using
Return bytes
End Function
Public Function Bytes2Object(ByVal bytes As Byte()) As Object
Using ms As New MemoryStream(bytes)
Dim ndcs As New NetDataContractSerializer
Return ndcs.Deserialize(ms)
End Using
End Function
Ursprünglich würden wir alle Ergebnisse als Objekt zurückgeben. Wenn das vom Dienst zurückkommende Objekt ein Byte-Array war, wussten wir, dass es eine Ausnahme war. Dann würden wir "Bytes2Object" aufrufen und die Ausnahme für die Behandlung auslösen.
Das Problem mit diesem Code ist, dass er nicht mit Silverlight kompatibel ist. Für unsere neuen Anwendungen habe ich die alten Methoden für schwer zu serialisierende Objekte beibehalten und nur für Ausnahmen ein paar neue Methoden erstellt. DataContractSerializer stammt ebenfalls aus dem System.Runtime.Serialization-Namespace, ist jedoch sowohl in der Windows- als auch in der Silverlight-Version vorhanden.
Public Function ExceptionToByteArray(obj As Object) As Byte()
If obj Is Nothing Then Return Nothing
Using ms As New MemoryStream
Dim dcs As New DataContractSerializer(GetType(Exception))
dcs.WriteObject(ms, obj)
Return ms.ToArray
End Using
End Function
Public Function ByteArrayToException(bytes As Byte()) As Exception
If bytes Is Nothing OrElse bytes.Length = 0 Then
Return Nothing
End If
Using ms As New MemoryStream
Dim dcs As New DataContractSerializer(GetType(Exception))
ms.Write(bytes, 0, bytes.Length)
Return CType(dcs.ReadObject(ms), Exception)
End Using
End Function
Wenn keine Fehler auftreten, gibt der WCF-Dienst 1 zurück. Wenn ein Fehler auftritt, übergibt er die Ausnahme an eine Methode, die "ExceptionToByteArray" aufruft, und generiert dann eine eindeutige Ganzzahl aus der aktuellen Zeit. Diese Ganzzahl wird als Schlüssel verwendet, um das Bytearray 60 Sekunden lang zwischenzuspeichern. Der WCF-Dienst gibt dann den Schlüsselwert an den Client zurück.
Wenn der Client feststellt, dass er eine andere Ganzzahl als 1 zurückerhalten hat, ruft er die "GetException" -Methode des Dienstes mit diesem Schlüsselwert auf. Der Dienst ruft das Byte-Array aus dem Cache ab und sendet es an den Client zurück. Der Client ruft "ByteArrayToException" auf und verarbeitet die Ausnahme wie oben beschrieben. 60 Sekunden sind ausreichend Zeit für den Client, um die Ausnahme vom Dienst anzufordern. In weniger als einer Minute wird der MemoryCache des Servers gelöscht.
Ich denke, das ist einfacher als das Erstellen einer benutzerdefinierten Ausnahmeklasse. Ich hoffe, dass dies später jemandem hilft.