Це стара тема, але варта іншої відповіді.
@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. Я сподіваюся, це пізніше допоможе комусь.