Exception Message: System.InvalidCastException: Unable to cast object of type "Standard.EntityClasses.BaseValidator" to type "SingletonTypeWrapper"
Stack Trace:
at SD.LLBLGen.Pro.ORMSupportClasses.SerializationWriter.SingletonTypeWrapper.Equals(Object obj)
at System.Collections.Hashtable.get_Item(Object key)
at SD.LLBLGen.Pro.ORMSupportClasses.SerializationWriter.WriteTokenizedObject(Object value, Boolean recreateFromType)
at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2.SerializeOwnedData(SerializationWriter writer, Object context)
at SD.LLBLGen.Pro.ORMSupportClasses.FastSerializer.WriteUnreferencedEntity(EntityBase2 entity, BitVector32 serializationFlags)
at SD.LLBLGen.Pro.ORMSupportClasses.FastSerializer.WriteCollection(IFastSerializableEntityCollection2 collection, BitVector32 serializationFlags)
at SD.LLBLGen.Pro.ORMSupportClasses.FastSerializer.WriteEntityMemberCollections(EntityBase2 entity)
at SD.LLBLGen.Pro.ORMSupportClasses.FastSerializer.WriteReferencedEntities(Object root)
at SD.LLBLGen.Pro.ORMSupportClasses.FastSerializer.Serialize(EntityBase2 entity)
at SD.LLBLGen.Pro.ORMSupportClasses.FastSerializer.Serialize(Object root)
at SD.LLBLGen.Pro.ORMSupportClasses.SerializationHelper.Serialize(EntityBase2 entity, SerializationInfo info, StreamingContext context)
at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2.GetObjectData(SerializationInfo info, StreamingContext context)
at SD.LLBLGen.Pro.ORMSupportClasses.EntityCore`1.System.Runtime.Serialization.ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at Standard.Extensions.EntityExtensions.CloneObject(Object toClone)
We see this a lot when serializing entities over remoting. However it is not at all consistent. The same remoting call works most of the time. We also capture errors when it's just serializing the entity but not transmitting over a network. The error listed above is specifically from an attempt at cloning an entity. In which we use the System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serialize and copy the entity into a MemoryStream and then create a new object from that MemoryStream. In the above stack trace the CloneObject code is ours. This is the CloneObject code being called:
private static object CloneObject(object toClone)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
bf.Serialize(ms, toClone);
ms.Seek(0, SeekOrigin.Begin);
return bf.Deserialize(ms);
}
}
Reviewing the source code we received with our license I'm able to determine there is something going on with the way the IValidator gets serialized. The BaseValidator listed in the exception is our code that gets applied to every one of our entities via a partial class:
public partial class CommonEntityBase
{
protected override IValidator CreateValidator()
{
return new BaseValidator();
}
}
It's largely there to handle sanitization of a view specific field types so they can save properly.
I suspect the exception is happening in equals overload of the SingletonTypeWrapper:
public override bool Equals(object obj)
{
return _wrappedType.Equals(((SingletonTypeWrapper)obj)._wrappedType);
}
Reading through the stack trace it seems the WriteTokenizedObject method is attempting to do a object lookup from the _objectTokenLookup Hashtable by using the validator class as the key. In this case it looks to me that it is using our BaseValidator as the key in the hash table causing each object in that hash table to do a comparison. But when we one of the SingletonTypeWrapper's in the hash table executes it's overloaded Equals operator it can't cast BaseValidator as SingletonTypeWrapper.
Would a simple guard clause in the Equals overload suffice here? Is there another approach I can use in our code?
Any insights would be appreciated as we can't even reliably replicate the issue right now.