|
Location: Home > Resources
> CustomExceptions
Custom Exceptions and .NET Remoting
2002
Ingo Rammer
Even though Remoting supports "High Type Fidelity", transferring custom Exceptions over Remoting boundaries comes with its very own challenge: using [Serializable] is not enough because the base class (System.Exception or System.ApplicationException) already implements ISerializable. If you want to pass your custom Exceptions over Remoting boundaries, you therefore have to override GetObjectData() and provide a custom constructor for deserialization. And don't forget to call MyBase.GetObjectData() (or base.GetObjectData() in C#)!
Please also note that your custom Exception has to be deployed to a shared DLL which is copied to, and referenced from, your client and server applications. It doesn't suffice to simply copy and paste the source code to your client and server project!
Any custom Exception you develop should be based on the following skeleton: Imports System
Imports System.Runtime.Serialization
<Serializable()> _
Public Class MyException
Inherits System.ApplicationException
Public Sub New(ByVal message As String)
MyBase.New(message)
End Sub
Public Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.New(info, context)
End Sub
Public Overrides Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.GetObjectData(info, context)
End Sub
End Class
If you want to transfer custom information with your Exception, you have to add them to the SerializationInfo-object on the call to GetObjectData() and to take them from this object in the secondary constructor: <Serializable()> _
Public Class ConcurrencyException
Inherits System.ApplicationException
Private _databaseTable As String
Public Sub New(ByVal message As String, ByVal databaseTable As String)
MyBase.New(message)
_databaseTable = databaseTable
End Sub
Public Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.New(info, context)
_databaseTable = info.GetString("_databaseTable")
End Sub
Public Overrides Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.GetObjectData(info, context)
info.AddValue("_databaseTable", _databaseTable)
End Sub
Public ReadOnly Property DatabaseTable() As String
Get
Return _databaseTable
End Get
End Property
End Class
If you wouldn't override GetObjectData() and/or don't provide the additional constructor Public Sub New(info, context), you would instead end up with a very different exception in your Catch-block: The constructor to deserialize an object of type General.ConcurrencyException was not found.
This Exception simply indicates that the client-side of the Remoting framework has not been able to correctly de-serialize your custom Exception (called General.ConcurrencyException in this sample).
|