Search code examples
c#serialization

Object serialization trouble (c#)


Dear Stack Overflow community, I thought I'd never have to ask this question, but apparently something is going wrong with serialization or my usage of it.

I have a class which I need to serialize:

[Serializable]
public class Device : ISerializable, IDisposable
{
   public delegate void ListChangedEventHandler(object sender, ListChangedEventArgs e);
   public string Name { get; set; }
   public string Description { get; set; }
   public string IPAddress { get; set; }

   [Browsable(false)]
   public ThreadSafeBindingList<Item> Items { get; set; }

    [Browsable(false)]
    public MibEntity AssociatedMibEntity { get; set; }
 
    //methods etc.
}

A little explanation:

ThreadSafeBindingList is inherited from System.ComponentModel.BindingList MibEntity is a class of SharpSNMP library (https://sharpsnmp.com/)

Problem: When I try to deserialize the object, MibEntity is always null. Other properties are fine. MibEntity class is in external dll, which I reference in the project where Device class resides.

This is its content:

[Serializable]
public class MibEntity 
{
    public MibEntity()
    {
        Children = new List<MibEntity>(); 
    } 
    
    [Browsable(false)]
    public List<MibEntity> Children { get; set; }

    [Browsable(true)]
    [Category("General")]
    public string OID { get; set; }

    private string _name;
    [Browsable(true)]
    [Category("General")]
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    [Browsable(true)]
    public string Description { get; set; }

    [Browsable(false)]
    public int Value { get; set; }


    [Browsable(true)]
    public AccessType AccessType { get; set; } //this is enum from SharpSNMP library

    [Browsable(true)]
    public Status Status { get; set; } //this is enum from same assembly as this class

    [Browsable(true)]
    public string Syntax { get; set; }

    [Browsable(true)]
    public bool IsTableEntry { get; set; }

    [Browsable(true)]
    public IDefinition IDefinition { get; set; } //this is interface from SharpSNMP library
}

I use BinaryFormatter for serialization and deserialization. Thank you for your help!


Solution

  • This invariably means you have made an error in your custom ISerializable implementation; the following works fine:

    protected Device(SerializationInfo info, StreamingContext context)
    {
        Name = info.GetString("Name");
        //...
        AssociatedMibEntity = (MibEntity)info.GetValue(
            "AssociatedMibEntity", typeof(MibEntity)); 
    }
    void ISerializable.GetObjectData(
        SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Name", Name);
        //...
        info.AddValue("AssociatedMibEntity", AssociatedMibEntity);
    }
    

    with validation:

    using (var ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, new Device {
            AssociatedMibEntity = new MibEntity { Name = "Foo"}});
        ms.Position = 0;
        var clone = (Device)bf.Deserialize(ms);
        Console.WriteLine(clone.AssociatedMibEntity.Name); // Foo
    }
    

    However, unless there is a good reason to implement ISerializable, you might be better served by simply removing your ISerializable implementation completely - noting that this will be a breaking change (any existing data won't deserialize correctly if you do this).

    [Serializable]
    public class Device : IDisposable // <=== no ISerializable; also removed
                                      // GetObjectData and custom .ctor
    

    Also: my usual rant: BinaryFormatter might not be your best bet if you are storing this data anywhere. It is... brittle. There are a range of far more reliable serializers.