繁体   English   中英

System.InvalidCastException "对象必须实现 IConvertible。" 使用 BinaryFormatter 反序列化字典时

[英]System.InvalidCastException "Object must implement IConvertible." when deserializing a Dictionary using a BinaryFormatter

[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; }
    }
}

此类被另一个 Serializable 类引用。

[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<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;
    }

实际的序列化/反序列化发生在这里:

    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;
    }

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

事实证明,因为我使用的是 NHibernate,所以它注入了它自己的集合实现。 为了完成这项工作,我必须在序列化/反序列化中使用接口 IDictionary:

    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> ) );
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM