C# System.InvalidCastException“;对象必须实现IConvertible。”;使用BinaryFormatter反序列化词典时

C# System.InvalidCastException“;对象必须实现IConvertible。”;使用BinaryFormatter反序列化词典时,c#,dictionary,binaryformatter,iserializable,C#,Dictionary,Binaryformatter,Iserializable,下面是调用序列化/反序列化代码的代码: [Serializable] public class UserOfCustomFields : MyObject, IUserOfCustomFields { public UserOfCustomFields( ) { this.CustomFields = new CustomFields( ); } protected UserOfCustomFields( SerializationInfo info,

下面是调用序列化/反序列化代码的代码:

[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; }
}
public bool SaveObjects(IEnumerable对象){
//如果我们有空对象,我们将失败
如果(objects==null){return false;}
var local_objects=objects.ToList();
var new_list=新列表>();
foreach(局部对象中的var obj){
var clone=this.DeepCopy(obj);
新列表。添加(克隆);
}
返回true;
}
实际的序列化/反序列化发生在这里:

    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;
    }
公共虚拟T-DeepCopy(T-obj)
{
如果(!obj.GetType().IsSerializable)
{
抛出新异常(“源对象必须可序列化”);
}
if(Object.ReferenceEquals(obj,null))
{
抛出新异常(“源对象不能为null”);
}
T结果=默认值(T);
使用(var memoryStream=newmemorystream())
{
var formatter=newbinaryformatter();
序列化(memoryStream,obj);
memoryStream.Seek(0,SeekOrigin.Begin);
结果=(T)格式化程序。反序列化(memoryStream);
memoryStream.Close();
}
返回结果;
}

如标题中所述,在反序列化时,我得到System.InvalidCastException“对象必须实现IConvertible.”。字典是特例吗?到目前为止,我还没有遇到任何其他类型的问题。

事实证明,由于我使用的是NHibernate,它注入了自己的集合实现。为了实现这一点,我必须在序列化/反序列化中使用接口IDictionary:

    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;
    }
受保护的自定义字段(SerializationInfo、StreamingContext)
:base(信息、上下文)
{
if(info==null)
抛出新的ArgumentNullException(“信息”);
this.CustomFieldDictionary=(IDictionary)info.GetValue(“CustomFieldDictionary”,typeof(IDictionary));
}
[SecurityPermission(SecurityAction.LinkDemand,
Flags=SecurityPermissionFlag.SerializationFormatter)]
公共覆盖无效GetObjectData(SerializationInfo、StreamingContext上下文)
{
if(info==null)
抛出新的ArgumentNullException(“信息”);
base.GetObjectData(信息、上下文);
//下线投掷
info.AddValue(“CustomFieldDictionary”,this.CustomFieldDictionary,typeof(IDictionary));
}

将调试器设置为在未处理异常时中断。您可能会发现字典中的对象没有实现IConvertibleIt不应该实现IConvertibleIt。我确实发现底层类型实际上是NHibernate.Collection.Generic.PersistentGenericMap,所以我想现在我需要发现为什么会是这种情况。从上面可以看到,它被定义为Dictionary。Dictionary是一个接口,许多类型都可以实现它。
    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;
    }
    protected CustomFields( SerializationInfo info, StreamingContext context )
        : base( info, context )
    {
        if( info == null )
            throw new ArgumentNullException( "info" );

        this.CustomFieldDictionary = ( IDictionary<string, string> ) info.GetValue( "CustomFieldDictionary", typeof( IDictionary<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 );

        // Following line throws
        info.AddValue( "CustomFieldDictionary", this.CustomFieldDictionary, typeof( IDictionary<string, string> ) );
    }