Search code examples
c#.netserializationderived-classbinary-serialization

How do you deserialize derived class while passing parameters to base class


I have a derived class that inherits from a bass class which draws a circle

    public BraceHole(Brace brace, Vertex centerPoint, double diameter, VDrawI5.vdEntities entities) : base(centerPoint, diameter / 2, entities)
    {
        this.brace = brace;
        this.centerPoint = centerPoint;
        this.radius = diameter/2;
    }

I am trying to serialize this class using binary serialization.

I am serializing it like so:

   public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("brace", brace, typeof(Brace));
        info.AddValue("radius", radius, typeof(double));
        info.AddValue("centerPoint", centerPoint, typeof(Vertex));
    }

The serialization seems to be okay, but when I de serialize it like below; I am getting the data fields (brace, radius and centerPoint) back okay; but I am not getting the circle back! I suspect it is because I am not de serializing the base class. However I try, I do not know how to do this!

    protected BraceHole(SerializationInfo info, StreamingContext context)
    {
       try {
            brace = (Brace)info.GetValue("brace", typeof(Brace));
            radius = (double)info.GetValue("radius", typeof(double));
            centerPoint = (Vertex)info.GetValue("centerPoint", typeof(Vertex));
        }
       catch{} 
    }

My question is how can I deserialize this. I am looking for something like this, is this possible?

  protected BraceHole(SerializationInfo info, StreamingContext context) : base(centerPoint, radius, entities)
    {
       VdProControl.VdProControl vectorDraw = (VdProControl.VdProControl)context.Context;
       VDrawI5.vdEntities entities = vectorDraw.ActiveDocument.Entities;

       try {
            brace = (Brace)info.GetValue("brace", typeof(Brace));
            radius = (double)info.GetValue("radius", typeof(double));
            centerPoint = (Vertex)info.GetValue("centerPoint", typeof(Vertex));
        }
       catch{} 
    }

Solution

  • What you need to do is both serialize the base class (which you are not currently doing) and have a protected constructor in the base class that takes in SerializationInfo and StreamingContext to deserialize it.

    //This is now a override of the virtual function defined in Circle
    public override void GetObjectData(SerializationInfo info, StreamingContext context)     
    {
        base.GetObjectData(info, context); //Get the base class data
        info.AddValue("brace", brace, typeof(Brace));
        info.AddValue("radius", radius, typeof(double));
        info.AddValue("centerPoint", centerPoint, typeof(Vertex));
    }
    
    protected BraceHole(SerializationInfo info, StreamingContext context) 
        : base(info, context) //Deserialize the base class data.
    {
       // The commented code would likely now go in the base class's protected constructor.
       //VdProControl.VdProControl vectorDraw = (VdProControl.VdProControl)context.Context;
       //VDrawI5.vdEntities entities = vectorDraw.ActiveDocument.Entities;
    
       try {
            brace = (Brace)info.GetValue("brace", typeof(Brace));
            radius = (double)info.GetValue("radius", typeof(double));
            centerPoint = (Vertex)info.GetValue("centerPoint", typeof(Vertex));
        }
       catch
       {
           //This empty try-catch is a bad idea, if something goes wrong you should 
           //at minimum log it some how. It would be better to get rid of it and let 
           //the caller catch the exception.
       } 
    }
    

    You will need to modify Circle to have the new constructor and the virtual method GetObjectData