title: System.InvalidCastException "Object must implement IConvertible." when deserializing a Dictionary using a BinaryFormatter
body: <pre><code>[Serializable]
  public class CustomFields : MyObject, ICustomFields // MyObject is marked as ISerializable
  {
      private IDictionary&lt;string, string&gt; _customFieldDictionary;
  
      public CustomFields( ) {
          this._customFieldDictionary = new Dictionary&lt;string, string&gt;( );
      }
  
      protected CustomFields( SerializationInfo info, StreamingContext context )
          : base( info, context )
      {
          if( info == null )
              throw new System.ArgumentNullException( "info" );
  
          // Following line throws
          this.CustomFieldDictionary = ( Dictionary&lt;string, string&gt; ) info.GetValue( "CustomFieldDictionary", typeof( Dictionary&lt;string, string&gt; ) );
      }
  
      [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&lt;string, string&gt; ) );
      }
  
      public virtual IDictionary&lt;string, string&gt; CustomFieldDictionary
      {
          get { return this._customFieldDictionary; }
          set { this._customFieldDictionary = value; }
      }
  }
  </code></pre>
  
  <p>This class is referenced by another Serializable class.</p>
  
  <pre><code>[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; }
  }
  </code></pre>
  
  <p>Here's the code that calls the serialization/deserialization code:</p>
  
  <pre><code>    public bool SaveObjects( IEnumerable&lt;IMyObject&gt; objects ) {
          // If we have null objects fail
          if ( objects == null ) { return false; }
  
          var local_objects = objects.ToList( );
          var new_list = new List&lt; IDBObject&lt; Guid &gt; &gt;( );
          foreach ( var obj in local_objects ) {
              var clone = this.DeepCopy( obj );
              new_list.Add( clone );
          }
  
          return true;
      }
  </code></pre>
  
  <p>And the actual serialization/deserialization  takes place here:</p>
  
  <pre><code>    public virtual T DeepCopy&lt;T&gt;( 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;
      }
  </code></pre>
  
  <p>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).</p>