Это старая ветка, но достойна другого ответа.
@ mson удивлялся, почему кто-то захочет сериализовать исключение. Вот наша причина сделать это:
У нас есть приложение Prism / MVVM с представлениями в Silverlight и WPF с моделью данных в службах WCF. Мы хотим быть уверены, что доступ к данным и обновления происходят без ошибок. Если есть ошибка, мы хотим немедленно об этом узнать и сообщить пользователю, что что-то могло не получиться. В наших приложениях появится окно, информирующее пользователя о возможной ошибке. Фактическое исключение затем отправляется нам по электронной почте и сохраняется в SpiceWorks для отслеживания. Если ошибка возникает в службе WCF, мы хотим получить полное исключение обратно клиенту, чтобы этот процесс мог произойти.
Вот решение, которое я придумал, которое может быть использовано как клиентами WPF, так и Silverlight. Методы ниже a в «общей» библиотеке классов методов, используемых несколькими приложениями на каждом уровне.
Массив байтов легко сериализуется из службы WCF. Практически любой объект может быть преобразован в байтовый массив.
Я начал с двух простых методов, Object2Bytes и Bytes2Object. Они преобразуют любой объект в байтовый массив и обратно. NetDataContractSerializer относится к версии Windows пространства имен System.Runtime.Serialization.
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
Первоначально мы возвращали бы все результаты в виде объекта. Если объект, возвращаемый из сервиса, был байтовым массивом, то мы знали, что это исключение. Затем мы вызываем «Bytes2Object» и выкидываем исключение для обработки.
Проблема с этим кодом в том, что он несовместим с Silverlight. Поэтому для наших новых приложений я сохранил старые методы для трудно сериализуемых объектов и создал пару новых методов только для исключений. DataContractSerializer также входит в пространство имен System.Runtime.Serialization, но присутствует как в версиях Windows, так и в Silverlight.
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
Когда ошибок не возникает, служба WCF возвращает 1. Если возникает ошибка, она передает исключение методу, который вызывает «ExceptionToByteArray», а затем генерирует уникальное целое число из настоящего времени. Это целое число используется в качестве ключа для кэширования массива байтов в течение 60 секунд. Служба WCF затем возвращает значение ключа клиенту.
Когда клиент видит, что получил целое число, отличное от 1, он вызывает метод GetException службы, используя это значение ключа. Служба извлекает байтовый массив из кэша и отправляет его обратно клиенту. Клиент вызывает «ByteArrayToException» и обрабатывает исключение, как я описал выше. 60 секунд - это достаточно времени для того, чтобы клиент запросил исключение из услуги. Менее чем за минуту, MemoryCache сервера очищается.
Я думаю, что это проще, чем создавать собственный класс Exception. Надеюсь, это кому-нибудь поможет позже.