[Serializable]
public class CustomFields : MyObject, ICustomFields // MyObject is marked as ISerializable
{
private IDictionary<string, string> _customFieldDictionary;
public CustomFields( ) {
this._customFieldDictionary = new Dictionary<string, string>( );
}
protected CustomFields( SerializationInfo info, StreamingContext context )
: base( info, context )
{
if( info == null )
throw new System.ArgumentNullException( "info" );
// Following line throws
this.CustomFieldDictionary = ( Dictionary<string, string> ) info.GetValue( "CustomFieldDictionary", typeof( Dictionary<string, string> ) );
}
[SecurityPermission( SecurityAction.LinkDemand,
Flags = SecurityPermissionFlag.SerializationFormatter )]
public override void GetObjectData( SerializationInfo info, StreamingContext context )
{
if( info == null )
throw new ArgumentNullException( "info" );
base.GetObjectData( info, context );
info.AddValue( "CustomFieldDictionary", this.CustomFieldDictionary, typeof( Dictionary<string, string> ) );
}
public virtual IDictionary<string, string> CustomFieldDictionary
{
get { return this._customFieldDictionary; }
set { this._customFieldDictionary = value; }
}
}
This class is referenced by another Serializable class.
[Serializable]
public class UserOfCustomFields : MyObject, IUserOfCustomFields {
public UserOfCustomFields( ) {
this.CustomFields = new CustomFields( );
}
protected UserOfCustomFields( SerializationInfo info, StreamingContext context ) : base(info, context)
{
if( info == null )
throw new System.ArgumentNullException( "info" );
this.CustomFields = ( CustomFields ) info.GetValue( "CustomFields", typeof( CustomFields ) );
}
[SecurityPermission(SecurityAction.LinkDemand,
Flags = SecurityPermissionFlag.SerializationFormatter)]
public override void GetObjectData( SerializationInfo info, StreamingContext context )
{
if( info == null )
throw new ArgumentNullException( "info" );
base.GetObjectData( info, context );
info.AddValue( "CustomFields", this.CustomFields, typeof( CustomFields ) );
}
public virtual ICustomFields CustomFields { get; set; }
}
Here's the code that calls the serialization/deserialization code:
public bool SaveObjects( IEnumerable<IMyObject> objects ) {
// If we have null objects fail
if ( objects == null ) { return false; }
var local_objects = objects.ToList( );
var new_list = new List< IDBObject< Guid > >( );
foreach ( var obj in local_objects ) {
var clone = this.DeepCopy( obj );
new_list.Add( clone );
}
return true;
}
And the actual serialization/deserialization takes place here:
public virtual T DeepCopy<T>( T obj )
{
if( !obj.GetType( ).IsSerializable )
{
throw new Exception( "The source object must be serializable" );
}
if( Object.ReferenceEquals( obj, null ) )
{
throw new Exception( "The source object must not be null" );
}
T result = default( T );
using( var memoryStream = new MemoryStream( ) )
{
var formatter = new BinaryFormatter( );
formatter.Serialize( memoryStream, obj );
memoryStream.Seek( 0, SeekOrigin.Begin );
result = ( T ) formatter.Deserialize( memoryStream );
memoryStream.Close( );
}
return result;
}
As noted in the title I get System.InvalidCastException "Object must implement IConvertible." when deserializing. Is Dictionary a special case? I've had no problems with any other types (up to now).
Turns out that since I'm using NHibernate that it injects it's own implementation of collections. In order to make this work I must use the interface IDictionary in the serialization/deserialization: