class AltSerialize<T> crashes when the serialiser tests the key class


Symptons: Serializer populates the Dictionary with empty key and value objects.
Cause: An exception is thrown while AltSerialize tests the serialisation speed of a blank key object. This exception is handled, but there is no catch clause to pick it up. It simply goes straight to the "finally". This leaves the poor end user with the need to compile the projects, run in it debug mode and a steep learning curve to isolate the problem! But we got there.
Exception thrown: the standard dictionary key already exists exception. (why would it do that in the phase where it is testing the serialisers with a blank object and an empty dictionary?)
Workaround: comment out the whole AltSerialize<T> class (good job I have implemented the ISerialize interface?), rebuild the project and it all springs into life.


Wobba wrote Feb 7, 2011 at 10:35 AM

Thanks for letting me know about this, and I'll be sure to fix it and include a test case.

wrote Feb 7, 2011 at 10:36 AM

Wobba wrote Feb 8, 2011 at 12:12 PM

Could you provide example code on a structure/class where it fails? The benchmarking to pick a serializer uses (T)Activator.CreateInstance(typeof(T), args) to instantiate a default object which is used to benchmark serialization/deserialization.

The error you get seems to be when an item is added to the dictionary, and that several objects get empty values when being serialized.

That said, when I get the time to work on this project and port it to .Net4, I will remove AltSerialize as it's not needed.

wmh wrote Feb 9, 2011 at 4:09 PM

Here is the class. I think I understand the probable mechanism now: have
a look at GetHash() and have a look at the default constructor (with the
default initialisation of pguid). However, this behaviour is as defined
by the requirements of my application. So the unfortunately the
serialiser has to cope with it (or the serialiser gets deleted!).

Before you ask, although my class looks like a basic reimplementation of a
perfectly good GUID object, I use this approach as a technique to ensure
that I dont cross-connect different ID objects that are used for different
purposes. Otherwise I get compile errors rather than runtime errors. OK,
GUIDs will always be unique so I dont need to worry too much but you can
spend a long time agonising about why your objects have disappeared when
you are using the wrong ID to start off with. I prefer compile errors at
the cost of a little extra code.

<Serializable()> _
Public Class PointGUID
Implements IEquatable(Of PointGUID)
Implements ISerializable

Private pguid As Guid = Guid.Empty

Public Shared ReadOnly Empty As PointGUID = New PointGUID
Public Shared Function NewGuid() As PointGUID
    Dim Result As PointGUID = New PointGUID
    Result.pguid = Guid.NewGuid
    Return Result
End Function

Public Shared Operator =(ByVal Left As PointGUID, ByVal Right As
PointGUID) As Boolean
    Return Left.pguid = Right.pguid
End Operator
Public Shared Operator <>(ByVal Left As PointGUID, ByVal Right As
PointGUID) As Boolean
    Return Not Left.pguid = Right.pguid
End Operator

Public Function Equals_PointGUID(ByVal other As PointGUID) As Boolean
Implements System.IEquatable(Of PointGUID).Equals
    Return pguid = other.pguid
End Function

Public Overrides Function GetHashCode() As Integer
    Return pguid.GetHashCode
End Function
Public Overrides Function ToString() As String
    Return pguid.ToString
End Function
Public Function ToGUID() As Guid
    Return pguid
End Function

Public Sub GetObjectData(ByVal info As
System.Runtime.Serialization.SerializationInfo, ByVal context As
System.Runtime.Serialization.StreamingContext) Implements
    info.AddValue("Point.pGUID", pguid, GetType(Guid))
End Sub

Public Sub New()
End Sub
Public Sub New(ByVal info As
System.Runtime.Serialization.SerializationInfo, ByVal context As
    pguid = CType(info.GetValue("Point.pGUID", GetType(Guid)), Guid)
End Sub
Public Sub New(ByVal GUID As Guid)
    pguid = GUID
End Sub
Public Sub New(ByVal PointGUIDString As String)
    pguid = New Guid(PointGUIDString)
End Sub
End Class

Wobba wrote Feb 11, 2011 at 10:59 AM

I can't seem to find out where the exception is thrown. When I try to instantiate a serializer with your class it works, and AltSerialize is returned. Feel free to post code which explains the error.

Here is my test code:
Factory<PointGUID> factory = new Factory<PointGUID>();
var serializer = factory.GetSerializer();
PointGUID a = new PointGUID(Guid.NewGuid());
PointGUID b = new PointGUID(Guid.NewGuid());
var a2 = serializer.BytesToObject(serializer.ObjectToBytes(a));
var b2 = serializer.BytesToObject(serializer.ObjectToBytes(b));
Assert.AreEqual(a.ToGUID(), a2.ToGUID());
Assert.AreEqual(b.ToGUID(), b2.ToGUID());

I can do test on AreEqual(a,a2) as well if I add this to your class, as a lot in .Net uses the non-generic version for comparison:

Public Overrides Function Equals(ByVal obj As Object) As Boolean
Return (Me.pguid = DirectCast(obj, PointGUID).pguid)
End Function

wrote Feb 14, 2013 at 12:12 AM